Now that we have defined our entity bean, we need to describe it to the EJB container. Our deployment descriptor, a file named ejb-jar.xml, is shown in Listing 5. We place ejb-jar.xml in $BOOK/il/co/lerner/book/, alongside the Java classes that will form our entity bean; when we build the bean with Ant, it will be placed in a subdirectory named META-INF.
The most interesting parts of ejb-jar.xml for an entity bean are the <persistence-type> section (set to “Container” for CMP), the <prim-key-field> and <prim-key-class> sections (in which we name the class of our primary key), and the <cmp-field> sections (which describe the container-managed fields to JBoss).
The deployment descriptor is a standard part of EJB and should work across all EJB servers and containers. However, it does not address all of the runtime configuration issues. For JBoss to work correctly, we thus include a file named jboss.xml that tells the server where we can find the beans on the network. A copy of jboss.xml, which we place alongside ejb-jar.xml in $BOOK/il/co/lerner/book/, is shown here:
<?xml version="1.0" encoding="UTF-8"?> <jboss> <enterprise-beans> <entity> <ejb-name>Book</ejb-name> <jndi-name>Book</jndi-name> </entity> </enterprise-beans> </jboss>
The source code for our simple test application, UseBook.java, is presented in Listing 6 [available at ftp.linuxjournal.com/pub/lj/listings/issue93/5577.tgz] and demonstrates how much you can do with very little code. It defines only a main() method and immediately goes about working with the EJBs. First it grabs a JNDI context and looks up the Book bean that we have defined. That allows it to create an instance of BookHome, which in turn lets us create a new instance of our Book bean:
Book book = home.create(testPrimaryKey, "Book title", "AuthorFirst AuthorLast", "PublisherName", 10.50);
As you can see, we've hard-coded the values we will add to the database, including the primary key. This is obviously unacceptable in the real world; a nonexample application would have taken the primary key (and other values) from a file, the command line, an environment variable, an HTML form on the Web or would have generated them automatically.
Notice how we never have to create SQL tables, insert rows or retrieve them. Our back-end persistent storage is presumably a relational database, but our Java client neither knows nor cares.
Once it has inserted a new row into the table, UseBook modifies some of its values (by setting instance variable values) and then retrieves all of the instances of Book in the database (with findAll()). Along the way, it sends status messages to System.out, which are printed on the console.
We use Ant, the Java replacement for the standard make program, to compile and install our program. Listing 7 [available at ftp.linuxjournal.com/pub/lj/listings/issue93/5577.tgz] shows our build.xml file, which compiles each of the .java source files from $BOOK/il/co/lerner/book, turns them into a jar file along with the deployment descriptor and JBoss runtime configuration file, and then installs the files into the JBOSS directory. If Ant is installed in ANT, you can compile all of the files, install them into the JBoss “deploy” directory and invoke UseBook.main() with:
As soon as JBoss notices the new (or updated) jar file, you will see output on the screen indicating what the server is doing. The output from Ant, by contrast, will display all of the items sent to System.out from within main(), including the status messages in Listing 6 that indicate what we have done. Each time you compile and run main() with a new ID value, a new row will be inserted into the database table.
Sun would like you to believe that EJB is the future of all server-side web applications. Microsoft, of course, is doing its utmost to convince you that .NET is the real future. How do independent developers fare in this war of giants, and what should free software advocates do?
The good news is that J2EE is an excellent architecture and philosophy. It's neither the most elegant nor the most flexible, and it does lock you into a single language. But overall, I'm impressed with J2EE and see it as an important milestone in the world of web application programming.
Unfortunately, there are a number of issues with J2EE that arise every time I use it to write an application. The first issue is that neither Java nor J2EE are open source, despite the fact that Java is free of charge and JBoss is licensed under the LGPL. Sun generally has been an honest player, but they are a commercial company with their own interests. Open-source advocates should not be surprised if and when Sun restricts the use of code or specifications.
In addition, the departure of Enhydra Enterprise appears to leave JBoss as the only open-source J2EE application server on the market. JBoss isn't officially certified as J2EE-compliant, however, because the JBoss team cannot pay for official certification. This strikes me as rather shortsighted of Sun; perhaps they could offer free or inexpensive certification for servers released under the GPL or LGPL, which (unlike the Berkeley license) ensure that no company could ever turn a certified server into a proprietary product. Official J2EE certification isn't important to me, but there are many CEOs and CTOs who do require it, which means that JBoss is often ignored for no good reason.
Java and EJB are complex, and it will take time for a programmer to learn about them. But the complexity of Java and EJB programming is dwarfed, in my experience, by a confusing array of configuration files, new terms, environment variables and other items that are unique to Java. Better documentation would certainly help, but it seems to me that a Java analogue to CPAN, which would make server-side Java configuration easier, would let programmers concentrate on programming rather than system maintenance issues.
Finally, the one part of .NET that really appeals to me is its relative openness to different programming languages. By definition, J2EE requires Java, which is often the right choice but should never be the only choice. SOAP and XML-RPC make it possible to bridge the gap between languages but without the nice transactioning and object-relational mapping that EJB brings to the table. For now, it seems that the only way for Python to speak to EJB is via SOAP or XML-RPC (or Jython), but I would love to see other possibilities in the future.
Editorial Advisory Panel
Thank you to our 2014 Editorial Advisors!
- Jeff Parent
- Brad Baillio
- Nick Baronian
- Steve Case
- Chadalavada Kalyana
- Caleb Cullen
- Keir Davis
- Michael Eager
- Nick Faltys
- Dennis Frey
- Philip Jacob
- Jay Kruizenga
- Steve Marquez
- Dave McAllister
- Craig Oda
- Mike Roberts
- Chris Stark
- Patrick Swartz
- David Lynch
- Alicia Gibb
- Thomas Quinlan
- Carson McDonald
- Kristen Shoemaker
- Charnell Luchich
- James Walker
- Victor Gregorio
- Hari Boukis
- Brian Conner
- David Lane