The new specification of Enterprise Java Beans (EJB) version 3 came out a little while ago. Now this may be an early draft, but the contours are already in place. It’s going to be different – very different. In this article we take a close look at every little detail… not. Rather, we attempt to take an overall view and check out some code!
The story so far….
Within J2EE, EJB has been seen as one of the heaviest technologies – not just for its complexity, but also from the point of view of the various factors involved in doing something. The list of “points for improvement” could be long. Onto the stage came Microsoft with its Dotnet, and began to use words like architecture. Sun, which still is used to sing in the final scene when it comes to creating major systems, realized that it had to be easier to develop with EJB, preferably without losing power. Cur- tain up! Enter EJB3 stage left!
Objectives
There were several objectives behind the new version.
New simpler configuration. Only state what is different – configuration by
exception.
- Encapsulate the beans to reduce dependency and knowledge of the world around. No artificial methods which are used, etc.
- Simpler persistence through simpler Java objects – ”Plain old java object” (Pojo).
- Support for lightweight modelling, easy to test outside the container (no need for heavy application servers).
- Support for inheritance, polymorphism, etc. Yes, that’s right! Actual object orientation!
- No checked exceptions, e.g. RemoteException.
- …and a whole pile of improvements.
In other words: easier, simpler and neater! Let’s take a closer look to see how successful they were.
Metadata
One of the first simplifications was to make use of the metadata which comes with Java 5 (JDK 1.5). To put it simply, it is a way of describing the code from a more comprehensive point of view. For example, why write long XML files when it should be enough just to say, “This method must be accessible from all machines.”
In our example, this will be ”@remote” in front of the method name. Obviously much simpler!
However, this has some unexpected effects. Now there are many new different meta settings and above all their default values. You don’t need to use all of them, but what is needed is new knowledge. Nevertheless, I still think it is better. The alternative would be to do as in the current version of EJB, where one is forced to always state values for all settings.
A simple bean
So let’s look at some code! A stateless session bean is the closest we get to “Hello World” with EJB.
Do you remember all those methods, for example ejbCreate, which had to be implemented despite being empty? And don’t forget the various interfaces and a description file with lots of XML.
Why not like this?
@Stateless @Remote public class FooBean { public void printBar() { System.out.println( ”Bar” ); } }
Much better the way I see it. Stateless indicates that this class is a stateless session bean. “Remote” indicates that it must be capable of being called from an- other machine. In reality more settings are needed but these either have standard values or are retrieved from the code. In the example we quote above, for instance, an interface file is generated, which we can later use in e.g. a client program which will call up the server.
And a session bean that saves its state isn’t all that much more difficult.
@Stateful public class BarBean { @Tx(TxType.REQUIRED) @MethodPermission(”guest”) public void orderSomething( String aDrink ) { ... } }
This time we had both transaction management and security. Note that it is just as easy to order an alcohol free alternative ;-).
A wilder bean
However, the great challenge with EJB 3 isn’t the session beans but the entity beans (CMP/BMP). The principle for saving these in a database has seen a real change. Gone are the monoliths that were connected to the mother ship, the application server.
An entity bean is marked with ”Entity”.
/** Our customer Pojo. */ @Entity public class Customer { private Long id; private String name; // A customer has one address. private Address address; private Set orders = new HashSet(); // Our primary key @Id(generate=SEQUENCE) public Long getID(){ return id; } protected void setID (Long id){ this.id =id; } // A customer has zero or many orders. @OneToMany(cascade=ALL) public Set getOrders(){ return orders; } public void setOrders(Setorders){ this.orders =orders } ...
All fields in the class are saved unless otherwise stated. Access to these fields is typically based on get and set methods in precisely the same way as for ordinary JavaBeans.
Both the name of the table and the columns are calculated in this case from the names we gave them in the code. Naturally, we can specify something different, but for the sake of simplicity we take a straightforward approach here. It is also possible to put the configuration in separate files – as previously – and in this way we could override the meta settings.
The first reference to another class is ”Address”. If it is marked as persistent, these instances are also read and written automatically.
Our primary key is “id”, which also contains information on how to generate new IDs.
We have also generated an Order pojo in a similar manner. The relation to this is written with “OneToMany”, as a customer has several orders. Order relates back to our Customer in the same way as the Address field above, thus the relation is two- way, which differs in outlook from a relational database. You will find an example of this further down in the article.
If we have read in a customer from the database, we have also automatically received that customer’s Orders. This will be an object tree where the root is the customer with his primitive values and references to the other sub-object Address and the list with Order.
Finally, the relation from customer to order is set as “cascade=ALL”, which speci- fies how events such as “save”, “delete”, etc are to be propagated. In the example we send all on to all order objects in the list.
Read a little, write a little
Let’s move on to retrieving a customer from the database. Therefore we insert a ses- sion bean that does just that. First we must acquaint ourselves with what replaces the application server – “EntityManager”. In a loose sense this class represents our database/session and manages the lifecycle for our pojos. It also contributes to gene- rating our queries (Query) to the database.
First a session bean:
@Stateless public class OrderEntryBean { @Inject private EntityManager em; //... }
Inject allows us to manage our pojos, i.e. get into the database – search, generate, etc. EntityManager can come from anything; it need not be an application server, but maybe a somewhat simpler test bench.
Now we can insert a method for searching for customers who have a certain name.
public List findByName (String name) { Query q = em.CreateQuery ( “SELECT c FROM Customer c ” + “WHERE c.name LIKE :custName ” ); q.setParameter(“custName ”,name); q.setMaxResults(10); return q.listResults(); }
The result is a list of the customers which matched the names we included. Re- trieving the value of these is quite simply a matter of looping over the list and calling up get and set methods.
Now we’ll make it a bit more difficult and add an order.
public void enterOrder(int custID, Order newOrder){ Customer c = em.find(“Customer ”,custID); c.getOrders().add(newOrder); newOrder.setCustomer(c); }
The relation is two-way and therefore they both require a reference to each other.
As yet the object is not in our database. Somewhere we have to tell our Entity- Manger to do the job and save our customer “c”.
em.create(c);
The customer is already in the database and will therefore be ignored. The event “save” will be sent on to sub-object (cascade=all) and the order we had stored in the database.
EJB QL
The new specification does not just involve simplifications. We also have entirely normal improvements to EJB QL, for example:
- bulk processing of delete and update,
- group by, having,
- sub and dynamic queries,
- and more functions (UPPER, CURRENT_DATE, etc) and so on.
One of my favourites is probably a polymorphism, which can already be used here:
SELECT avg(e.salary) FROM Employee e
So if Manager now inherits from Employee, we will obtain an calculated mean value for everyone – both ordinary employees and managers. Though maybe it is a less interesting example to mix up salaries like this ;-).
When and how?
If we use the number of pages in the specification as a mark of how much more needs to be done, then there is a lot. EJB 2.1 weighs in with a brave 646 pages. The draft of version 3 is more modest with 93. Moreover, many aspects invite discussion. At the time of this writing a second draft has been released. It is now divided into two documents – persistence is kept seperately. Combined they land at nearly 200 pages.
It’s going to take time. I hardly dare guess where the horizon lies. Shall we say a year before the specification is ready? And should we add another year until it is generally available? True enough, this is my pessimistic side talking – I hope. There are already some versions which, so to speak, comply with the standard. That’s why “now” is a good time to prepare for what is to come.
Would you like to have a deeper understanding of what it’s like to develop such a solution? Trying out a Hibernate/Xdoclet combo is good idea since it is so similar EJB3 persistence. If you are interested in experimenting, JBoss has a beta version of the EJB specification based on Hibernate.
Brave new EJB?
Yes, in fact. Sun has chosen the right path to take. And for that they deserve praise. It requires courage to break with old doctrines. The “old” EJB was a heavy affair which hasn’t exactly made life any easier for us programmers. But – and there’s always a but – the new specification is both simpler and more complex. The complexity is tied up with the new power that object orientation, pojos, etc gives us. But extra
power tends to require extra learning. There are going to be quite a few more ups and downs before we can set the “pedal to the pojo”.
Resources JSR #220 http://www.jcp.org Hibernate http://www.hibernate.org Jboss http://www.jboss.com
Originally published in JayView.
Leave a Reply