Register for Real-World Java Seminar
The Java Platform, Enterprise Edition, or Java EE, is the most popular middleware platform for developing and deploying enterprise applications. Java EE offers developers a choice of vendors, portability, scalability, and robustness. However, it has been criticized for its complexity and its need for a lot of redundant and procedural code. In addition, lightweight frameworks such as Spring and scripting platforms such as Ruby on Rails have emerged to challenge the platform's supremacy in the middleware world.
In response, the Java Community Process has made great efforts to simplify the developer's life with Java EE's latest incarnation: Java EE 5. Innovations such as radically simplified models for Enterprise JavaBeans (EJB) and Web services have changed how enterprise applications are built using Java EE 5 technologies. Combining the robustness of the Java EE platform with lightweight frameworks such as Spring further enables developers to rapidly develop portable, maintainable enterprise applications.
In this two-part series, I will discuss how Java EE 5 simplifies enterprise application development, then uncover how you can utilize the Spring Framework to fill the gaps left by Java EE 5.
Simplified Programming Model with Java EE 5
Java EE 5 radically simplifies the development of enterprise applications by:
Let's briefly examine these changes.
Simplified Persistence
Most developers who used the EJB 2 container-managed persistence were disappointed with its complexity and performance. As a result, POJO persistence frameworks such as Hibernate and TopLink became popular, compelling the Java Community Process to standardize a persistence API for the Java platform on a POJO persistence model.
If you've used an object-relational (O/R) mapping framework to build the persistence tier of your application, you'll notice that each framework provides three facilities:
The EJB 3 Java Persistence API (JPA) standardizes the use of persistence for the Java platform by providing a standard mechanism for O/R mapping, an EntityManager API to perform CRUD operations, and a way to extend the EJB query language (EJB-QL) to retrieve entities.
Introducing JPA Entities
An entity is a lightweight domain object - a plain old Java object that you want to persist in a relational database. Like any POJO, an entity may be either an abstract or a concrete class, and it can extend another POJO. You can use the @javax.persistence.Entity annotation to mark a POJO to be an entity, as shown in Listing 1.
(The code examples that follow are taken from my recently published book, EJB 3 in Action, published by Manning Publications.)
I've used annotations to define the mapping of entities to tables; you can also use XML. It's worth mentioning that JPA provides support for rich domain modeling capabilities such as inheritance, and polymorphism. JPA supports several inheritance mapping strategies: single table, joined subclass, and table per class. Unlike EJB 2 container-managed persistence (CMP), JPA is simple and supports automatic generation of primary keys.
Now that you've seen an entity, let's examine how you can manipulate entities by using the EntityManager API.
The EntityManager API
The javax.persistence.EntityManager manages entity lifecycles and exposes several methods to perform CRUD operations on entities. JPA supports two types of EntityManager: container-managed and application-managed. The application-managed EntityManager is really useful when using JPA outside a container. Let's look at an example of using a container-managed EntityManager to manage an entity.
You can use the persist() method to save an instance of entity. For example, if you want to persist an instance of Bid, use the following code:
@PersistenceContext(unitName="actionBazaar")
private EntityManager em;
...
Bid bid = new Bid();
bid.setItem(item);
bid.setBidder(bidder);
bid.setBidPrice(price);
em.persist(bid);
Now that you have a sense of how easy it is to use the persistence feature of EJB 3, we'll examine how EJB 3 simplifies the development of business components.
Simplified EJB 3 Components
EJB 2 was one of the primary technologies responsible for the complexities that have plagued enterprise Java development. Some detractors ridiculed it as a "fat elephant" for its heavyweight nature. It required a lot of redundant code, even to build a simple "HelloWorld" EJB.
EJB 3 simplifies development by adopting the POJO programming model, and simplifies usage of EJB and resources by using dependency injection. It also depends heavily on intelligent defaults and makes the deployment descriptor optional.
Listing 2 provides an example of a simple stateless EJB 3 session bean with a remote interface. In this example, PlaceBidBean is a simple POJO class that implements a regular Java interface - or a plain old Java interface (POJI). The @javax.ejb.Remote converts the POJI to a remote interface and @javax.ejb.Stateless converts the POJO to a stateless EJB.
You can use @Stateful and @MessageDriven annotations to define stateful and message-driven beans, respectively.
Dependency Injection
With Java EE 5, invoking an EJB component is a snap with dependency injection. Dependency injection support in Java EE 5 was influenced by inversion of control (IoC) containers such as Spring.
Dependency injection is essentially the opposite of the JNDI: the container is responsible for looking up and instantiating an instance of an EJB or a resource. Figure 1 depicts how dependency injection compares with JNDI.
For example, in Figure 1 you can invoke the EJB from a managed component as follows:
@EJB
private PlaceBid placeBid;
..
Long bidId = placeBid.addBid(bid);
..
Although Java EE 5 simplifies usage resources and services by using dependency injection, it is supported only on managed classes such as Java servlets, listeners, and EJBs, and not regular Java classes. Later I'll discuss how you can use Spring's powerful dependency injection features to fill that gap.
Note that Listing 2 uses JMS Queue to send messages. The @Resource annotation injects an instance of JMS connection factory and destination, respectively, without having to do a complex JNDI lookup. Usage of JMS is fairly complex, but Spring simplifies it with its JmsTemplate, as we will see in the second part of this article.
Simplified Web Service
Development of Web services was incredibly complex with the Java API for XML-based RPC (JAX-RPC), which was part of earlier versions of J2EE. The Java API for XML Web services (JAX-WS), part of the Java EE 5 platform, simplifies the development and invocation of Web services by using annotations. You can easily expose any POJO or stateless EJB as a Web service by using the @WebService annotation. For example, you can expose the PlaceBid EJB as shown in Listing 3.
If you have used Web services in J2EE 1.4, you'll realize how simple it is to develop Web services in EJB 3!
The invocation of Web services was also a complex task with J2EE 1.4. Java EE 5 simplifies it by using @WebServiceRef annotations, as shown here:
@WebServiceRef(wsdlLocation="http://localhost:8888/PlaceBidService/PlaceBidService?WSDL")
private static PlaceBidService placeBidService;
actionbazaarplacebidservice.PlaceBidBean placeBid = placeBidService.getPlaceBidBeanPort();
System.out.println("Bid Successful, BidId Received is:" +placeBid.addBid
("idiot", Long.valueOf(1), 2000005.50 ));
Again, however, @WebServiceRef injection is only supported with managed classes and cannot be used from regular Java objects.
In the first half of the article, I discussed how Java EE 5 simplifies development of enterprise Java applications. Now I'll explore how you can use Spring to address limitations in Java EE.
Integrating the Power of Java EE 5 and Spring
The Spring Framework provides a lightweight container with functionality that simplifies the development of applications. Although many view Spring as an alternative to Java EE, most customers use it as a framework and deploy Spring-based applications into a Java EE container such as Oracle Containers for J2EE (OC4J).
Spring simplifies resource access by using dependency injection, and simplifies database access by using a template-based approach. In this section, I'll take a look at these capabilities.
JPA and Spring
Spring has wide support for data access that includes popular object-relational mapping (ORM) frameworks, including Hibernate and TopLink. Spring takes a data access object (DAO) approach to coding, allowing developers to use these ORM options and switch between them easily. While JdbcTemplate makes database access using JDBC simpler, Spring 2.0 has built-in integration with JPA, and it ships TopLink Essentials (the reference implementation of JPA derived from Oracle TopLink in Sun's GlassFish project) as the default JPA provider.
While Spring supports container-managed EntityManager as a lightweight container, it simplifies usage of JPA with JpaTemplate. Table 1 shows several Java interfaces for using JPA in Spring.
Spring enables you to access and manipulate entities either using JPA directly or using JpaTemplate. I will now demonstrate how to use JPA from applications using JpaTemplate. Listing 4 shows a DAO implementation class using JpaTemplate.
You can use the JpaTemplate methods to access entities. Spring really simplifies some of the repetitive usage of EJB 3 JPA. For example, if you want to use a dynamic query to retrieve all bids for an item, you can use the JpaTemplate to produce this:
List bids = getJpaTemplate().find("SELECT b FROM Bid b WHERE b.item = ?1",item);
The equivalent code, if you use the EntityManager API, will look like this:
List bids = em.createQuery("SELECT b FROM Bid b WHERE b.item = ?1")
.setParameter(1,item).getResultList();
The real power of Spring comes from how it configures services via dependency injection. To use JPA with Spring, you need the configuration shown in Listing 5.
JPA is not the only cool thing about EJB 3; there is more meat in it, and there are more integration points between Spring and EJB 3 that we will discover in the next part of this series.
Conclusion
In this article, you learned how Java EE 5 simplifies the development of enterprise-level applications. You saw examples of JPA entities, EJB 3 session beans, and a simple JAX-WS Web service. All these components are POJOs and make heavy use of annotations. JPA greatly simplifies the building of persistence applications.
The Spring Framework 2.0 has not only integrated with JPA, but also greatly simplifies usage of JPA by using JpaTemplate. In the next part of the series we will discover how the Spring Framework integrates with other components such as an EJB, Java Message Service (JMS), and transaction manager. Stay tuned!