There are some major waves in J(2)EE territory captivating much of the focus of the audience at this year’s JavaPolis – and beyond. One undoubtedly is Java Server Faces. Others include the AJAX, Spring Framework, AOP and SOA & WebServices, as well as probably Java Desktop that seems to be making a revival. Perhaps the biggest wave of them all is: EJB 3.0, especially Persistence. Object Relational mapping, java applications talking to databases, the impedance mismatch: it is the cornerstone of most Java applications. The J2EE platform was built from 1999, initially primarily focused on EJB. I was surprised to learn that EJB actually predates J2EE by almost two years. However, EJB clearly has not delivered on its promises and expectations. Many alternative implementations for the Persistency side of Java Applications and the O/R mapping challenge were created. Most notable are – at this moment – Hibernate, Oracle TopLink and the JDO specification and several of its implementations such as KODO.
Things are going to change. EJB 3.0 will finally provide the specification for pragmatic, easy to use and easy to configure and functionally rich persistency. And wait, there is more – as my TellSell ad would say – it also delivers a Reference Implementation (required for JSRs to be finalized) of Industrial Strength and an Open Source License. That means that not only will EJB 3.0 give us a standard persistency specification that will fix most problems that were created by EJB in the past – it will also make an implementation available that is free, open source and quite good. Sun and Oracle teamed up to create this RI; most of it is the Sun application server with a stripped down version of Oracle TopLink, a product that has been doing Object/Relational mapping for over 10 years (it even predates Java!).
Mike Keith presenting on EJB 3.0
The most important presentation I attended at JavaPolis was by Mike Keith, Co-Specification Lead for JSR-220 (EJB 3.0) and member of the Expert Group for JSR-244 (JEE 5) and Architect for Oracle TopLink and the EJB Container in OC4J – the J2EE Application Server from Oracle. He spoke about EJB 3.0 – Persistency, as you will have gathered by now. He started by drawing a picture of the history of EJB and J2EE – as it used to be called. EJB was created – as Mike described it – by a more or less randomly picked bunch of people, very much associated with Sun, certainly not a presentative group of industry experts. EJB was supposed the panacee for many problems in Java applications at the time – such as complexity, scalability, productivity etc. – but it fell short as most of us have come to realize. Mike specifically concluded that EJB was:
- not simple
- not as interoperable as it was inteded to be and we were led to believe
- not as functionally rich as was required
- very hard to unit-test due to the dependencies on the J2EE container
Subsequent releases have remedied some of these problems to some extent, but EJBs are definitely not as popular as they once were. The dissatisfaction they generated even fueled an entire new branch of open source projects, of which the Spring Framework is the most notable one. The JDO specification can also be seen as a reaction to EJBs. Of course EJBs are more than a database persistency framework – they also provide distributed capabilities and container managed services.
The EJB 3.0 Persistency specification caters not just for in-Container persistency, it also provides a stand-alone route, using J2SE Bootstrapping. That means that applications can be tested and run outside a J(2)EE container and still benefit from the standardization and RI. It also means that you program against the Persistency Specification and choose your O/R implementation independently.
The roadmap for EJB 3.0 is as follows:
- Christmas 2005: proposed final draft
- New Year 2006: Reference Implementation ready (that means a fully functional implementation is available and can be put to use right away)
- Final Release before JavaOne 2006 (May)
- First certified implementations in JEE 5 containers shortly afterwards (Oracle is already offering an OC4J preview implementation of EJB 3.0, as is JBoss EJB 3.0) (The EJB 3.0 Persistence specification allows you to use the new persistence API
in plain Java applications. JBoss EJB 3.0, also gives you the ability to use
Session Beans and Message Driven Beans out of the application server in standalone programs,
junit tests, standalone Tomcat, and even other application servers.)
What is Persistency? And what is it in EJB 3.0?
In Java, objects live in memory. All objects are instantiated by the Java program. When all threads end, when the JVM dies (ending all threads) and when the plug is pulled on the computer (ending the JVM, ending all threads), all objects come to an end. However, in many cases, you do not want the objects to die. After carefully collecting all customer, order, payment and shipping details in your web store, it would be a waste to just let go of all those objects! You would not know where to ship, what to ship and how to receive payment. You would be a pathetic shop! So you want to ‘persist’ the objects, make them permanent, in a less volatile environment than just memory.
The file system presents itself as a candidate storage mechanism and as Java support serialization, that is a way to go. However, finding and reviving objects from their serialized state is quite somewhat cumbersome. It also means that your persistent data is only available to Java programs. A more common approach, as I am sure you are well aware of, is the use of a database, typically a relational database, for back end storage. Databases have a relatively easy interface – SQL and JDBC – and provide many facilities that are beneficial to most applications. Think performance, data integrity, multi-user support, scalability, backup & recovery etc. They have one big dasadvantage from the perspective of Java programs: usually they do not talk objects. They speak in terms of database records, table rows and columns.
This is what we tend to call the ‘impedance mismatch’ between the OO and the relational world. It is this gap that O(O)/RM frameworks attempt to solve. And it is what EJB 3.0 Persisentce is all about. Your application has or needs objects, your database has or needs records. What is there to do?
The usual approach is to specify mappings. This meta-data – usually a voluminous bundle of XML data – that relates objects to tables and properties to columns. Properties that reference another class/object map to foreign keys in the database. Then there is the O/R Mapping Framework that reads the mapping meta-data and provides services to find, query, create, remove or update objects that map to relational tables. By invoking these services, SQL operations through JDBC are put in motion by the O/R framework. This is how Hibernate works. It is also how TopLink, JDO, OJB, ADF BC and many others function. It is in a manner of speaking also how EJB 2.1 and before persistence works. However, all these frameworks and technologies have their own, non-interchangeable format for the mapping meta-data. And they each have their own way of acquiring a Session object that provides the services and their own way for invoking those services. Basically, if you use one particular O/R Mapping Framework, your code is pretty much tied into it. If you change to another O/R technology, you have to change your code, your meta-data and – perhaps even more important – you have to acquire a whole new skillset: you have to learn how to use this new framework.
EJB 3.0 strives to achieve several goals:
- A standard way for specifying the mapping information – one that is interoperable between all implementations of the Persistence API
- A simple way for specifying the mapping information – one that does not require piles of XML
- A standard set of Persistency services – generic methods that create, find, query, update and remove objects
- A persistence API that supports both container managed persistence and bean-managed persistence inside a J(2)EE container as well as stand-alone persistence for container-independent J2SE applications
- An API that is not intrusive – the domain objects (the objects that are mapped to relational database objects) should be allowed to be part of domain specific inheritance for example and they should not be forced to implement persistency related interfaces: Power to the POJO
- Facilities that allow different vendors to plug in their own implementations – competition in this space should be encouraged, even under the generic API
- Leverage best practices, knowledge and successes from EJB 2.1, JDO and other O/RM technologies
- Enhance the EJB QL language with frequently requested yet lacking features such as bulk update and delete operations, outer join operations, projection, and subqueries
Mike Keith showed us in what was a very entertaining presentation what EJB 3.0 is doing in order to achieve these goals. I will repeat that: in a very entertaining presentation. That is an achievement – to be entertaining about a persistence API! Mike congratulated us several times on still being in the room. He was not quite sure he would have managed the same thing being in the audience himself. But apart from being very educational, the stories behind the facts and the pleasure that Mike was visibly radiating enthousiasm and even pleasure at telling us his stories.
A small sideline: At one point Mike remarked something like “there was not much activity along the excitement path”; I thought this to be a very British way of saying that it was boring. When Mike subsquently went ‘out about in a boat’ several times, I became quite convinced he is Canadian. Which is a very fine thing. I am curious though whether my conclusion was correct. Mike, if by chance you are reading this, could you comment?
The EJB 3.0 Persistence API prescribes the use of Java 5.0 Annotations for specifiying the Mapping information. There you have it. No more separate XML files. It is all part of the code. And it is “configuration by exception”: you only need to configure what is really special. Many default values will suffice in most cases, simplifying the mapping configuration details required enormously. And these annotations are generic and fully portable between JEE 5 compliant containers and out-of-container implementations of the Persistence API. And they are simple, yet functionally rich. Somewhat advanced – yet frequently needed – features are supported, like
- Database generated primary key values
- Multi-table mapping
- Many-to-Many relationships
- Lazy Fetch
- Cascading operations
- Entity Life Cycle callbacks – the Java equivalent of database triggers.
- Inheritance for domain objects – mapping to one or multiple tables, constituing a type-hierarchy
- Named Queries – define once, use many times
The specification does not cater for any type of cache, clustering or locking. It does allow raw SQL to be used when the EJB QL language is found lacking for specific queries; the results of such Native Queries can still be mapped to the entities.
EJB 3.0 expects you to get hold of an EntityManager object. This object implements the interface that defines a number of services, “such as create
, which puts an entity bean in a managed state (that is, what’s termed a “persistence context”) and remove
,
which removes an entity bean from the persistence context. When a bean
instance is in a managed state, the data it represents is inserted into
a database at the end of a transaction. The EntityManager
also provides a flush
method which synchronizes the persistence context with the underlying
database. The data represented by a managed entity bean instance is
inserted into a database when flush
is issued, that is, before the end of the transaction. When a bean instance is removed through remove
,
it’s no longer in a managed state — the data it represents is removed
from the database at the end of a transaction, or sooner if flush
is specified.
Some other important methods provided by the EntityManager include find, which finds an entity bean instance by primary key, and merge, which merges the state of a detached entity bean instance into the current persistent context. The entity bean model in the EJB 3.0 architecture allows for detaching entity beans instances. An entity bean instance becomes detached at the end of a transaction. Detached instances can exist outside of the transaction context in which they were created. This allows a developer to do things such as serialize the bean instance to another application tier. This is a significant improvement over older versions of the entity bean model. Previously, entity beans were not serializable. Developers had to resort to a Data Transfer Object (DTO) to export an entity bean’s state. In general, DTOs are not viewed positively. They’re seen as “antipatterns,” that is, bad solutions to a problem. The merge method brings the state of a detached instance into the persistence context. ”
[this is a citation from the article Ease of Development in Enterprise JavaBeans Technology, By Ed Ort, October 2004 – Sun Developer Network (SDN)]
Getting hold of an EntityManager for code running inside a container is extremely simple:
@Inject EntityManager em;
This statement instructs the container to inject an EntityManager instance in the variable em. Subsequently, the application code can access em for its services, to find entities, manipulate them etc.
Outside of the container, it is somewhat trickier to get to an EntityManager object. Mike showed the code, but I did not jot it down, assuming it would be easy to find on the internet. Well, it is not so easy to find. After a lot of googling, the best I could do is this link: How-To Build out-of-container example using EJB 3.0, a how-to by Shannon Chen from Oracle, that describes out-of-container usage of an EntityManager instance using Oracle Toplink.
Mike repeated the following lines several times to let it sink in: “In EJB 3.0 an Entity is NOT an Entity Bean! An Entity is NOT a (container managed) Component (with lots of configuration overhead). An Entity is simply POJO that has been enabled to be persistent.” Now you read it several times as well.
EJB 3.0 is about standardizing what people are doing. Not forcing people to follow a standard that is largely a laboratory invention, a theoretical artefact [like EJB prior to 3.0]. That was the first take-away from this presentation. The second: EJB 3.0 provides an industrial strength, open source implementation! And the last one: if Mike Keith ever comes to a theater near you, be sure to go and see him!
Some simple syntax examples of EJB 3.0 mappings
Declare a class Employee to be persistence enabled, mapped to a table EMP:
@Entity @Table(name="EMP") public class Employee {...}
Specify the Primary Key of the Employee, mapping the property to the column EMPNO:
@Id @Column(name="EMPNO") public String getEmployeeNumber() { return employeeNumber; }
Also see: How-To Configure the TopLink EJB 3.0 Mapping Annotations – by Guy Pelletier on OTN
Indicate how a collection of details can be found, tracing back a Foreign Key reference:
@OneToMany(cascade=PERSIST) @JoinColumn(name="MGR", referencedColumnName="EMPNO") public Collection getManagedEmployees() { return managedEmployees; }
Resources
Java Community Process – homepage for JSR-220 EJB 3.0
EJB 3.0 Resources on the Oracle Technology Network
Dali – Eclipse plugin : The goal of the
Dali EJB Object-Relational Mapping project is to
build extensible frameworks and exemplary tools for the
definition and editing of Object-Relational (O/R) mappings
for EJB 3.0 Entity Beans.
Mike Keiths Weblog: System.out
Loosely Coupled Blog by Raghu Kodali
Ease of Development in Enterprise JavaBeans Technology, By Ed Ort, October 2004 – Sun Developer Network (SDN)
POJO Application Frameworks: Spring Vs. EJB 3.0, by Michael Juntao Yuan, 06/29/2005 OnJava.com
The EJB 3.0 Hibernate Fallacy – shocking and revealing blog-post with comment-thread including strong language by Gavin King
Out-of-Container testing harness – by Debu Panda on Oracle Technology Framework
Still not supported in a very direct way – something you just don’t do unless you are a enthousiastic Database programmer – is the derivation of values inside the database through Defaults defined on columns or inside Database Triggers. Only database generated Primary Key values are directly supported through an attribute in the @Id annotation. When you know that an Before Row Insert or Update trigger may set or change values on the record, you have to explicitly tell the EntityManager to flush and refresh directly after a create and update. Not pretty. Then again, you can hardly expect a generic persistency API to leverage features like Oracle’s Returning Clause that you can use to return the values of specific columns immediately following a DML statement.