Developing with POJOs, Page 2
Once you break free of the constraints imposed by the EJB 2 programming model, implementing the object model shown in figure 1.2 is easy. Java provides all of the necessary features, including fine-grained objects, relationships, inheritance, and recursion. It is straightforward to implement expressive object models like this one using POJOs and thus benefit from improved maintainability and testability. Java is an object-oriented language, so it is foolish not to use its capabilities.
As a bonus, POJOs have these other important benefits:
- Easier development—There is less cognitive load because rather than being forced to think about everything—business logic, persistence, transactions etc.—at once you can instead focus on one thing at a time. You can first design and implement the business logic and then, once that is working, you can deal with persistence and transactions.
- Faster development—You can develop and test your business logic outside of the application server and without a database. You do not have to package your code and deploy it in the application. Also, you do not have to keep the database schema constantly in sync with the object model or spend time waiting for slow-running database tests to finish. Tests can run in a few seconds and development can happen at the speed of thought—or at least as fast as you can type!
- Improved portability—You are not tied to a particular implementation technology. The cost of switching to the next generation of Java technology is minimized because you have to rewrite only a small amount of code, if any.
I was genuinely surprised by how POJOs changed how I went about development because I'd become so accustomed to the cumbersome EJB approach. As with the TiVo box I described earlier, I had to use them before I appreciated their true value. But now I couldn't imagine reverting to the old way of working. Of course, you still need to handle persistence and transactions, which is where lightweight frameworks come in.
When the time comes to persist the POJOs that implement the business logic, there are some powerful object/relational mapping frameworks to choose from. The main ones are JDO, which is a standard from Sun, and Hibernate, which is an extremely popular open source framework. In addition, the specification for EJB 3 entity beans appears to be potentially quite powerful.
Transparent persistence with JDO and Hibernate
JDO and Hibernate provide transparent persistence, which means that the classes are unaware that they are persistent. The application just needs to call the persistence framework APIs to save, query, and delete persistent objects. The persistence framework automatically generates the SQL statements that access the database using an object/relational mapping, which is defined by XML documents or Java 5 annotations. The object/relational mapping specifies how classes map to tables, fields map to columns, and relationships map to either foreign keys or join tables. JDO and Hibernate can also run outside of the application server, which means that you can test your persistent business logic without deploying it in a server. You can, for example, simply run tests from within your integrated development environment (IDE).
Encapsulating the calls to the persistence framework
Even though Hibernate and JDO provide transparent persistence, some parts of an application must call the JDO and Hibernate APIs to save, query, and delete persistent objects. For example, TransferService must call the persistence framework to retrieve the accounts and create a BankingTransaction. One approach is for TransferService to call the persistence framework APIs directly. Unfortunately, this would couple TransferService directly to the persistence framework and the database, which makes development and testing more difficult.
A better approach is to encapsulate the Hibernate or JDO code behind an interface, as shown in figure 1.2. The persistence framework, which in this example is Hibernate, is encapsulated by the repository classes. Each repository consists of an interface and a Hibernate implementation class and is responsible for one type of object. The JDO implementation would be similar.
Figure 1.2 Using repositories to encapsulate the persistence framework hides the persistence details from the rest of the application.
In this example, repositories call the Hibernate APIs to access the database. AccountRepository finds accounts and BankingTransactionRepository creates BankingTransactions. The TransferService is written in terms of the AccountRepository and BankingTransactionRepository interfaces, which decouples it from the persistence framework and the database. By the intelligent use of interfaces, you can avoid coupling your domain logic to a particular persistence framework. This will enable you to test the domain model without the database, which simplifies and accelerates testing. It also enables you to use a different persistence framework if your needs change. For example, changing this application from Hibernate to JDO or even EJB 3 is simply a matter of changing the concrete classes that access the persistence framework. It's a generally accepted observation that loosely coupled applications are easier to maintain and test.
Part two of this series offers information on how to
- Eliminate DTOs
- Return domain objects to the presentation tier
- Make POJOs transactional
- Manage these transactions with Spring
About the Author
Chris Richardson is a developer and architect with over 20 years of experience. His consulting company specializes in jumpstarting projects and mentoring teams. Chris has been a technical leader at Insignia, BEA, and elsewhere. He has a computer science degree from the University of Cambridge in England and lives in Oakland, CA.
About the BookThis material reprinted with permission and is based on material from Chapter 1 of POJOs in Action.
|POJOs in Action|
By Chris Richardson
Published: January, 2006, Paperback: 592 pages
Published by Manning Publications
Retail price: $44.95