Get to know Java EE 5

Major enhancements mean faster, easier -- and simplified -- enterprise application development

An overview of the new Java™ EE 5 specification, its many significant enhancements, and what it means for your WebSphere® applications.

Roland Barcia, Certified IT Specialist, EMC

Photo: Roland BarciaRoland Barcia is a Consulting IT Specialist for IBM Software Services for WebSphere. He is a co-author of IBM WebSphere: Deployment and Advanced Configuration.


developerWorks Master author level
        2

August 2007 (First published 25 July 2007)

Also available in Chinese Russian Japanese

Introduction

A look at the history of the Java Platform, Enterprise Edition (Java EE) specification reveals that each major revision has been driven by a major theme. For example, with the first release of J2EE™ 1.2 came the initial bundling of separate specifications, and later, in J2EE 1.4, the focus was on Web services. Figure 1 shows a historical summary of Java EE, listing important features from each version, along with some key external influences that has helped shape it.

Figure 1. History of Java EE
Figure 1. History of Java EE

As with most early versions of new technologies, a number of "pain points" surfaced in prior versions of the Java EE specification, including:

  • Complexity of business logic programming.
  • Complexity and performance of the persistence programming model.
  • Presentation layer/logic mix.
  • Types, complexity, document model, extension, and performance of Web services.
  • Multi-member team development.
  • Lengthy edit-compile-debug cycle.

It comes as no surprise, then, that the theme of the Java EE 5 specification is simplification, an objective that has been achieved by improving the development experience in these areas:

  • Simplified business logic development.
  • Simplified testing and dependency management.
  • Simplified O/R persistence.
  • Enhanced Web services programming model.

Many of the upgrades in Java EE 5 have been influenced by innovative technologies in both the commercial and open source space, such as Hibernate, Spring, Service Data Object (SDO), and other technologies. In addition, there is also the expected upgrades in specification levels with minor enhancements.

To prepare you for working with Java EE 5, this article highlights some major features of the new specification, such as EJB 3.0, Java Persistance Architecture (JPA), Web services, JAX-WS, and others, and then takes a brief look ahead at what we might be able to expect from Java EE 6.


EJB 3.0

Of all the technology enhancements in Java EE 5, Enterprise JavaBean™ (EJB) 3.0 is by far the most significant, having received a major cosmetic change that dramatically simplifies development. The EJB 3.0 specification specification has been split into three sub-specifications:

  • EJB 3.0 Simplified API: Defines the new simplified API used to code EJB components, specifically session beans and message-driven beans.

  • Core Contracts and Requirements: Defines the EJB contracts between the bean and the EJB container.

  • Java Persistence Architecture API: Defines the new entity bean model for persistence.

The next sections describe updates to EJB 3.0 and the JPA API.

EJB 3.0 simplification

POJO (Plain Old Java Objects) is a term that has been tossed about a lot lately, referring to code written as plain Java classes. Because EJB 2.x programs require that you extend specific classes, provide several interfaces, and write deployment descriptors, they are viewed as "overloaded" Java objects that are no longer plain; rather, you need a J2EE container to run and test them. EJB 3.0 changes that:

  • EJB components no longer require home interfaces. In addition, EJB components are no longer required to provide different interfaces or extend any EJB-specific classes.

  • J2SE 5.0 annotations are now a major facilitator for implementing EJB 3.0 components. By specifying special annotations, developers can create POJO classes that are EJB components, as an alternative to XML.

  • EJB 3.0 introduces the notion of a business interface, rather than separate remote and local interfaces. An example of this is shown below:

    Listing 1
    public interface Stock
    {
    	public double getQuote(String symbol);
    }

    Your bean class can implement the interface:

    Listing 2
    @Stateless public class StockBean implements Stock
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    The @Stateless annotation, in the example above, means that this class is now a stateless session bean, and the business interface is used to invoke it. A stateless session bean can also be coded without implementing a specific interface, and the container can generate one for you:

    Listing 3
    @Stateless public class StockBean
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    Now that you have one interface, how do you specify whether the methods are remote or local? Of course, you can use an annotation:

    Listing 4
    @Remote
    	public interface Stock
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    You can annotate either the business interface or the bean class itself. Enabling the annotation on the bean class is useful when you choose to generate the business interface.

Updates to the EJB 3.0 specification include:

  1. Container services
  2. Callbacks
  3. Interceptors
  4. Dependency injection
  1. Container services

    EJB components are popular because of the implicit support for transaction management and security. The EJB 3.0 specification uses annotations (in addition to XML) to apply container services. Here is an example of how you would specify a transactional attribute on a stateless session bean:

    Listing 5
    @Stateless public class StockBean
    {
    
    @TransactionAttribute(TransactionAttributeType.REQUIRESNEW)
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    The annotation means that the method will be run in a new transaction. See the specification for specific syntax and semantics of the different annotations, but the same transactional and security features all have annotations. Container services can also be applied using XML deployment descriptors, which can also provide an override for annotations enabling flexibility at deployment time.

  2. Callbacks

    What about callbacks? Prior to EJB 3.0, you had to implement callback methods, such as ejbCreate(), on the bean class; bean classes had to implement all the methods, whether they used them or not. In most cases, these method implementations were empty. Callbacks are now handled through annotations as well, using either callback methods or callback listener classes. Here is an example of how you could write code to respond to a callback using callback methods:

    Listing 6
    @Stateless public class StockBean implements Stock
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    
    	@PostConstruct initializeCache()
    	{
    	}
    }

    The above code enables you to implement code after a bean instance is created. If you wanted to use a callback listener, you could create a callback listener class:

    Listing 7
    public class MyCallbackListener
    {
    	@PrePassivate public clearCache(Object obj)
    	{
    		Stock stock = (Stock) obj;
    		//perform logic
    	}
    }

    A callback class that is not part of the bean class has to take in a java.lang.Object parameter. The container will then pass the bean instance. A bean class adds the callback listener class by using a special callback annotation at the bean class level:

    Listing 8
    @CallbackListener MyCallbackListener
    @Stateless public class StockBean implements Stock
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    Callbacks are nice because the inclusion of them in your code is conditional, unlike when you implement interfaces.

  3. Interceptors

    A nice addition to the EJB specification is the use of interceptors. One thing missing from EJB components has been the ability to perform Aspect Oriented Development (AOP) for things like pre/post-processing and cross cutting concerns, much like servlet filters do for servlets. You can now develop an interceptor class and apply it to a bean. Here is an example of an interceptor that audits invocations of the StockBean class:

    Listing 9
    public class StockRequestAudit {
    	@AroundInvoke
    	public Object auditStockOperation(InvocationContext inv) throws
    	Exception {
    		try {
    			Object result = inv.proceed();
    			Auditor.audit(inv.getMethod().getName(), inv.getParameters[0]);
    			return result;
    		} catch (Exception ex) {
    			Auditor.auditFailure(ex);
    			throw ex;
    		}
    	}
    }

    The interceptor above intercepts the call to the target EJB method, then calls the proceed() method on the InvocationContext. This enables the call to flow through to the actual EJB method that was invoked. After the target EJB method returns, it uses the metadata in the InvocationTarget to get the method name and parameters of the target EJB component that was called. The interceptor can then be applied to the bean class:

    Listing 10
    @Stateless @Interceptors({StockRequestAudit})
    public class StockBean implements Stock
    	public double getQuote(String symbol)
    	{
    		return 100.33;
    	}
    }

    Additionally, you can develop interceptor methods that are implemented inside the bean class -- and also specify multiple interceptors, in which case the order in which they are called is specified by the order in which they are defined in the bean class. Interceptors can also be applied using XML away from the bean, which is preferred in AOP, since you want to transparently apply cross cutting concerns to beans.

  4. Dependency injection

    EJB code dependencies (on things like data sources) and the manner in which EJB components are invoked by EJB clients are some of the things that can make EJB development testing difficult. The EJB 3.0 specification introduces dependency injection as a mechanism to alleviate such difficulties. Instead of using JNDI lookups, an EJB can define a resource reference by injecting code. Here is an example of an EJB bean that needs to call another EJB component and use a data source to do JDBC work:

    Listing 11
    @Stateless public class StockBean implements Stock
    {
    @EJB(name="MarketBean", businessInterface="Market")
    Market market;
    
    @Resource(name="StockDB, resourceType="javax.sql.DataSource")
    DataSource stockDS
    
    	public double getQuote(String symbol)
    	{
    		Connection con = stockDS.getConnection();
    		//DO JDBC work
    
    			return market.getCurrentPrice(symbol);
    	}
    }

    Dependency injection can occur in a variety of ways, such as through a setter method or a class variable. See the specification for more details.

Java Persistence Architecture (JPA)

The specification for EJB persistence has changed significantly. Known as Container Managed Persistence (CMP), it defined no mapping layer and was managed by the container; therefore, it was up to the vendor to implement mappings. Influenced by several commercial and open source products and technologies, such as Hibernate, Java Data Objects (JDO), and TopLink, EJB 3.0 introduces a new style of persistence, POJO-based persistence:

  • Modeled on successful patterns.
  • Simplifies JDBC access patterns.
  • Can be integrated with Web services.
  • Container stays out of the way; you can use JPA in a Java EE or Java SE environment.
  • Standardized O/R mapping metadata.
  • Support for top-down, meet-in-the-middle, and bottom-up development.
  • Support for disconnected and connected objects states, eliminating the need for separate Data Transfer Objects. Figure 2 shows an example.
Figure 2. Supporting object states
Figure 2. Supporting object states

Updates to the JPA API include:

  1. Types: Entities and tables
  2. Instances: Java objects
  3. Attributes: Java properties and column annotations
  4. Dependent objects: Embedded Java objects
  5. Derived attributes: Transient annotation
  6. Key attributes: Annotated fields and key classes
  7. Relationships: Annotations and join columns
  8. Constraints: Annotations and database
  9. Inheritance: Annotations -- Single table, joined table, and table per class
  1. Types: Entities and tables

    Types for JPA are entities (no longer called entity beans), which can be mapped to tables. The main vehicle for mapping is by annotating the entity class. Below is an example of a mapping between a Customer Java Object and a CUSTOMER table:

    Listing 12
    @Entity
    @Table(name="CUSTOMER")
    public class Customer implements Serializable {
    ...

    A class is annotated as an entity and annotated with the customer. A deployment descriptor can be used as an alternative or as an overriding mechanism.

  2. Instances: Java objects

    Applications interact with Java objects at run time. Through the use of a special object called the entity manager, applications can query or persist objects. An entity manager is injected into an application using dependency injection within an EJB container (or, it can be looked up by an EntityManagerFactory in a Java SE environment). Here is an example:

    Listing 13
    @PersistenceContext (unitName="db2")
    private EntityManager em;

    Applications can retrieve objects or pass them into the entity manager. Here is an example of an application using the entity manager to find an object by its primary key:

    Listing 14
    Customer customer = (Customer)em.find(Customer.class,customerId);

    Here is another example of creating a Java object and persisting to a database by passing it to the entity manager:

    Listing 15
    CustomerOrder newOrder = new CustomerOrder();
    newOrder.setStatus("OPEN");
    newOrder.setTotal(new Integer(0));
    newOrder.setCustomerId(customerId);
    em.persist(newOrder);
  3. Attributes: Java properties and column annotations

    Attributes are Java properties in a class. Java properties can be mapped to database columns through the @column annotation. There are two forms of mapping properties: Field or Property (default):

    Listing 16
    @Entity(access=FIELD)
    @Table(name="PRODUCT")
    public class Product implements Serializable {
    
    	@Id
    	@Column(name="SKU")
    	Integer sku;
    
    	@Column(name="DESC")
    	String description;
    
    	@Column(name="PRICE")
    	Integer cost;
  4. Dependent objects: Embedded Java objects

    JPA has support of dependent objects. You can create a special object called an embeddable object, which is defined by annotating a class with @Embeddable:

    Listing 17
    @Embeddable
    public class CustomerAddress {
    private int streetAddress;
    private String city;
    private String state;
    private String country;
    ...
    }

    You can then define that object as a field on an entity class:

    Listing 18
    @Entity
    @Table(name="CUSTOMER")
    public class Customer {
    	private String name;
    	private CustomerAddress ca;
    
    @Embedded
    @AttributeOverrides({
    @AttributeOverride(name="streetAddress", column=@Column("
    STRT_ADD")),
    @AttributeOverride(name="city", column=@Column("CITY"))
    ... //more
    })
    	public CustomerAddress getCustomerAddress()
    {
    
    ...
    }

    Using the special attribute override, you can map the fields of the embeddable class within the entity. An alternative is to directly map the columns on the embeddable class.

  5. Derived attributes: Transient annotation

    By default, all fields are persistent in JPA; however, you can mark a field as transient, and then you can derive any field using logic. Below, a query is executed to derive a field:

    Listing 19
    @Transient
    public Integer getTotal() {
    
    	Query totalLineItems = em.createNamedQuery("getOrderTotal");
    	totalLineItems.setParameter("orderId",orderId);
    	Integer result = (Integer)totalLineItems.getSingleResult();
    	return result;
    }
  6. Key attributes: Annotated fields and key classes

    JPA supports several flavours of primary keys, plus various flavours of key generation. In the simple case, you can annotate a field on your entity as a primary key with the @Id annotation:

    Listing 20
    @Entity
    @Table(name="CUSTOMER")
    public class Customer implements Serializable {
    
    	private Integer id;
    	private String name;
    	private CustomerOrder currentOrder;
    	
    		
    	@Id
    	@Column(name="CUST_ID")
    	public Integer getId() {
    		return id;
    	}
    	public void setId(Integer id) {
    		this.id = id;
    	}
    ...

    You can also create a primary key class for entities that have composite keys:

    Listing 21
    public class LineItemId implements Serializable {
    
    	private Integer orderId;
    	private Integer productId;
    	public LineItemId() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	@Column(name="ORDER_ID")
    	public Integer getOrderId() {
    		return orderId;
    	}
    	public void setOrderId(Integer orderId) {
    		this.orderId = orderId;
    	}
    	
    	@Column(name="PRODUCT_ID")
    	public Integer getProductId() {
    		return productId;
    	}
    	public void setProductId(Integer productId) {
    		this.productId = productId;
    	}
    	public boolean equals(Object arg0) {
    		if (arg0 == this) return true;
    		    if (!(arg0 instanceof LineItemId)) return false;
    			LineItemId other = (LineItemId)arg0;
    			if(other.getOrderId().equals(orderId) &&
    				other.getProductId().equals(productId))
    			{
    				return true;
    			}
    			return false;
    		
    	}
    	public int hashCode() {
    		return orderId + productId.hashCode();
    	}
    
    }

    You can then define the composite key on your entity using the @IdClass annotation:

    Listing 22
    @Entity
    @Table(name="LINEITEM")
    @IdClass(LineItemId.class)
    public class LineItem implements Serializable {

    Your entity class must have matching fields on the class or it can embed the key as an embeddable key:

    Listing 23
    @Entity
    @Table(name="LINEITEM")
    @IdClass(LineItemId.class)
    public class LineItem implements Serializable {
    	private LineItemId lineItemId;
    
    	@EmbeddedId
    public LineItemId getLineItemId()
    	{
    		return lineItemId;
    	}
    
    ...

    Another major enhancement is the support for generating primary keys. By using the generate attribute of the @Id annotation, you can select a different strategy. For example, you can choose to delegate primary key generation to a DB2 identity column, as shown here:

    Listing 24
    @Id(generate=GeneratorType.IDENTITY)
    @Column(name="ORDER_ID")
    public Integer getOrderId() {
    	return orderId;
    }
    public void setOrderId(Integer orderId) {
    	this.orderId = orderId;
    }

    Other supported mechanisms include sequence and table generation.

  7. Relationships: Annotations and join columns

    JPA has strong support for relationships between entities. JPA supports one-to-one, one-to-many, many-to-one, and many-to-many relationships. In JPA, relationships are not bi-directional, as they are in EJB 2.x. Instead, objects declare other entities as members and annotations are added to define the relationship. You can make a relationship bi-directional by using a special attribute. Below is an example of a CustomerOrder class with two different relationships:

    Listing 25
    @Entity
    @Table(name="CUSTOMER")
    public class Customer implements Serializable {
    
    	
    	private Integer id;
    	private String name;
    	private CustomerOrder currentOrder;
    	
    		
    	@Id
    	@Column(name="CUST_ID")
    	public Integer getId() {
    		return id;
    	}
    	public void setId(Integer id) {
    		this.id = id;
    	}
    	
    	@Column(name="NAME")
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	
    	@OneToOne(cascade=CascadeType.ALL , fetch=FetchType.EAGER )
    	@JoinColumn(name="OPEN_ORDER_ID",referencedColumnName="ORDER_ID")
    	public CustomerOrder getCurrentOrder() {
    		return currentOrder;
    	}
    	public void setCurrentOrder(CustomerOrder currentOrder) {
    		this.currentOrder = currentOrder;
    	}
    
    }

    In this relationship, the Customer is defined with a one-to-one relationship with CustomerOrder by annotating the CustomerOrder property in the Customer class. The JoinColumn information is also defined. The name attribute defines the foreign key on the table to which the Customer class is mapped, and the referenced column defines the primary key to which the Table CustomerOrder is mapped. Any constraints on the relationship are defined as an attribute to the @OneToOne annotation. The CustomerOrder class is shown below. CustomerOrder also has Customer property defined; however, the CustomerOrder object has a one-to-many relationship back to the Customer. This is because a Customer can have only one current order; in actuality, a customer can have many orders, and so CustomerOrder shows this. However, the mappedBy attribute is used here to define that CustomerOrder is mapped by the Customer class on the other side of the relationship. The class is shown below:

    Listing 26
    public class CustomerOrder implements Serializable {
    	private Integer orderId;
    	private String status;
    	private Integer total;
    	private Integer customerId;
    	private Collection<LineItem> lineItems;
    	private Customer customer;
    	
    	@Column(name="CUSTOMER_ID")
    	public Integer getCustomerId() {
    		return customerId;
    	}
    	public void setCustomerId(Integer customerId) {
    		this.customerId = customerId;
    	}
    	
    	@Id(generate=GeneratorType.IDENTITY)
    	@Column(name="ORDER_ID")
    	public Integer getOrderId() {
    		return orderId;
    	}
    	public void setOrderId(Integer orderId) {
    		this.orderId = orderId;
    	}
    	@Column(name="STATUS")
    	public String getStatus() {
    		return status;
    	}
    	public void setStatus(String status) {
    		this.status = status;
    	}
    	@Column(name="TOTAL")
    	public Integer getTotal() {
    		return total;
    	}
    	public void setTotal(Integer total) {
    		this.total = total;
    	}
    
    	@ManyToOne(fetch=FetchType.EAGER,optional=false)
    	  @JoinColumn(name="CUSTOMER_ID",
    	     referencedColumnName="CUST_ID",insertable=false,updatable=false,
    	     nullable=false,unique=true) 
    	  public Customer getCustomer() {
    	     return customer;
    	  }
    	  public void setCustomer(Customer customer) {
    	     this.customer = customer;
    	  }
    	  @OneToMany(mappedBy="customerOrder", cascade=CascadeType.ALL ,
    	     fetch=FetchType.EAGER)
    	  public Collection<LineItem> getLineItems() {
    	     return lineItems;
    	  }
    	  public void setLineItems(Collection<LineItem> lineItems) {
    	     this.lineItems = lineItems;
    
    	}
    
    }

    Another relationship in CustomerOrder contains a collection of LineItem objects. This is a one-to-many relationship. Notice that JRE 5 defines the use of generics, specifying the type of collection. The special mappedBy attribute is used again here, making it a bi-directional relationship mapped by the other side of the relationship.

    Listing 27
    @Entity
    @Table(name="LINEITEM")
    @IdClass(LineItemId.class)
    public class LineItem implements Serializable {
    	
    	private Product product;
    	private Integer orderId;
    	private Integer productId;
    	private Integer quantity;
    	private Integer total;
    	private CustomerOrder customerOrder;
    	
    	@Column(name="QUANTITY")
    	public Integer getQuantity() {
    		return quantity;
    	}
    	public void setQuantity(Integer quantity) {
    		this.quantity = quantity;
    	}
    	
    	@Column(name="AMOUNT")
    	public Integer getTotal() {
    		return total;
    	}
    	public void setTotal(Integer total) {
    		this.total = total;
    	}
    	
    	  @ManyToOne(fetch=FetchType.EAGER,optional=false)
    	  @JoinColumn(name="PRODUCT_ID",
    	     referencedColumnName="SKU",insertable=false,updatable=false,
    	     nullable=false,unique=true)
    	  public Product getProduct() {
    	     return product;
    	  }
    	  public void setProduct(Product product) {
    	     this.product = product;
    	  }
    	
    	@Column(name="ORDER_ID")
    	public Integer getOrderId() {
    		return orderId;
    	}
    	public void setOrderId(Integer orderId) {
    		this.orderId = orderId;
    	}
    	
    	@Column(name="PRODUCT_ID")
    	public Integer getProductId() {
    		return productId;
    	}
    	public void setProductId(Integer productId) {
    		this.productId = productId;
    	}
    	  @ManyToOne(fetch=FetchType.EAGER,optional=false)
    	  @JoinColumn(name="ORDER_ID",
    	     referencedColumnName="ORDER_ID",insertable=false,updatable=false,
    	     nullable=false,unique=true)
    	  public CustomerOrder getCustomerOrder() {
    	     return customerOrder;
    	  }
    	  public void setCustomerOrder(CustomerOrder customerOrder) {
    	     this.customerOrder = customerOrder;
    	  }
    
    }

    The LineItem class has a CustomerOrder property. There is a many-to-one relationship defined here, as shown above. Similarly, the LineItem class has a many-to-one relationship to the product object as well.

    Another type of mapping is when a table might have a one-to-one relationship but your object model only has one object. In other words, you want to map a single object across tables (sort of the opposite of a dependent object). You can do this by adding one or more secondary tables. Below is an example that maps the customer object across the Customer and Order tables.

    Listing 28
    @Entity
    @Table(name="CUSTOMER")
    @SecondaryTable(name="ORDER ",
    pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))
    public class Customer { ... }
  8. Constraints: Annotations and database

    Besides supporting the various database constraints, JPA enables you to define constraints on the various relationships:

    Listing 29
    @OneToMany(mappedBy="customerOrder", cascade=CascadeType.ALL , 
    fetch=FetchType.EAGER)
    	public Collection<LineItem> getLineItems() {
    		return lineItems;
    	}
    	public void setLineItems(Collection<LineItem> lineItems) {
    		this.lineItems = lineItems;
    	}

    The cascading affect is shown in this example. For example, if a customer is deleted, so should the order. Below is an example with more constraints:

    Listing 30
    @ManyToOne(fetch=FetchType.EAGER,optional=false)
    @JoinColumn(name="CUSTOMER_ID", referencedColumnName="CUST_ID",
    	insertable=false,updatable=false, nullable=false,unique=true) 
    
    public Customer getCustomer() {
    	return customer;
    }
    public void setCustomer(Customer customer) {
    	this.customer = customer;
    }

    Above, a many-to-one relationship is defined across a foreign key that is also part of a primary key. In this example, no one is allowed to update or insert into that column, which is also marked as unique and not nullable. The relationship is also specified as not optional. JPA also enables you to define unique constraints on specific entities, as shown here:

    Listing 31
    @Entity
    @Table(
    name="EMPLOYEE",
    uniqueConstraints=
    {@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"})}
    )
  9. Inheritance: Annotations -- Single table, joined table, and table per class

    The JPA specification defines three types of support for mapping inheritance; only one is mandatory in the current specification:

    • Single table: The object tree is mapped to one table.
    • Joined table: (Optional) The child class is mapped to a table that has a foreign key relationship to the table to which the parent is mapped.
    • Table per-class: (Optional) Each concrete subclass is mapped to a table and contains columns for super class attributes.

    Here is an example of mapping a super class and a sub class using the single table strategy:

    Listing 32

    Click to see code listing

    Listing 32

    @Entity
    @Table(name="CUST")@Inheritance(strategy=SINGLE_TABLE,discriminatorType=STRING,discriminatorValue="CUST")
    public class Customer { ... }
    
    
    @Entity
    @Inheritance(discriminatorValue="VCUST")
    public class ValuedCustomer extends Customer { ... }

    Here is an example using the joined table strategy:

    Listing 33
    @Entity
    @Table(name="CUST")@Inheritance(strategy=JOINED,discriminatorType=STRING,discriminatorValue="CUST")
    public class Customer { ... }
    
    @Entity
    @Table(name="VCUST")@Inheritance(discriminatorValue="VCUST")@PrimaryKeyJoinColumn(name="CUST_ID")
    public class ValuedCustomer extends Customer { ... }

See Resources to explore the many more features available in JPA.


JAX-WS

Java EE 5 also introduces a new programming model for Web services: JAX-WS. Before looking at what is different, you might want to know what has not changed from JAX-RPC to JAX-WS:

  • JAX-WS still supports SOAP 1.1 over HTTP 1.1, so interoperability will not be affected. The same messages can still flow across the wire.
  • JAX-WS still supports WSDL 1.1, so what you've learned about that specification is still useful. A new WSDL 2.0 specification is nearing completion, but it was still in the works at the time that JAX-WS 2.0 was finalized.

The article series Web services hints and tips: JAX-RPC versus JAX-WS contains details on JAX-WS, but here is a summary of what has changed from JAX-RPC 1.1 to JAX-WS 2.0:

  • SOAP 1.2: JAX-RPC and JAX-WS support SOAP 1.1. JAX-WS also supports SOAP 1.2.
  • XML/HTTP: The WSDL 1.1 specification defined an HTTP binding, which is a means by which you can send XML messages over HTTP without SOAP. JAX-RPC ignored the HTTP binding. JAX-WS adds support for it.
  • WS-I Basic Profiles: JAX-RPC supports WS-I's Basic Profile (BP) version 1.0. JAX-WS supports BP 1.1. (WS-I is the Web services interoperability organization.)
  • New Java features: JAX-RPC maps to Java 1.4. JAX-WS maps to Java 5.0. JAX-WS relies on many of the features new in Java 5.0. (Java EE 5, the successor to J2EE 1.4, adds support for JAX-WS, but it also retains support for JAX-RPC, which could be confusing to Web services novices.)
  • Data mapping model: JAX-RPC has its own data mapping model, which covers about 90 percent of all schema types. Those that it does not cover are mapped to javax.xml.soap.SOAPElement. (The JAX-WS data mapping model is JAXB, which promises mappings for all XML schemas.)
  • Interface mapping model: JAX-WS's basic interface mapping model is not extensively different from JAX-RPC's, however the JAX-WS model makes use of new Java 5.0 features, and introduces asynchronous functionality.
  • Dynamic programming model: JAX-WS's dynamic client model is quite different from the JAX-RPC mode. Many of the changes acknowledge industry needs, including message-oriented and dynamic asynchronous functionality. JAX-WS also adds a dynamic server model, which JAX-RPC does not have.
  • Message Transmission Optimization Mechanism (MTOM): JAX-WS, via JAXB, adds support for MTOM, which is the new attachment specification, which should make attachment interoperability become a reality.
  • Handler model: The handler model has changed quite a bit from JAX-RPC to JAX-WS. JAX-RPC handlers rely on SAAJ 1.2, whereas JAX-WS handlers rely on the new SAAJ 1.3 specification.

JAX-WS also works with EJB 3.0 to simplify the programming model. For example, the code below shows how easy it is to make an EJB 3.0 POJO into a Web service:

Listing 34
@WebService public interface StockQuote {
    public float getQuote(String sym);
}

@Stateless public class QuoteBean implements StockQuote {
	public float getQuote(String sym) { ... }
}

Other annotations have been added to support more advanced features in Web services. JAX-B provides a standard mapping between POJOs (Listing 35) and XML schemas (Listing 36), an example of which is shown below:

Listing 35
@XmlType
public class Trade {
	@XmlElement(name="tickerSymbol")
	public String symbol;
	@XmlAttribute
	int getQuantity() {...}
	void setQuantity() {...}
}
Listing 36
<xs:complexType name="trade">
	<xs:sequence>
	<xs:element 
		name="tickerSymbol"
		type="xs:string"/>
	</xs:sequence>
	<xs:attribute name="quantity"
		type="xs:int"/>
</xs:complexType>

JavaServer Faces

JavaServer™ Faces (JSF) has been around for a few years now and is supported by most Java EE application servers, such as IBM® WebSphere Application Server. In Java EE 5, JSF is now part of the Java EE 5 specification. JSF provides many benefits to Java EE applications:

  • Rich, extensible, UI components.
  • Event driven.
  • Managed component state.
  • Renderer/client independence.
  • Validators.
  • Type conversion.
  • Externalized navigation.
  • Common JavaServer Pages and Faces Expression Language.

Looking forward to Java EE 6

A proposal was recently put out for JSR 316 (Java EE 6), and although it is still early in the specification definition, the proposal highlighted a few major themes:

  • Extensibility: By adding more extensibility points and more service provider interfaces, other technologies can plug into platform implementations cleanly and efficiently, enabling growth.

  • Profiles: Profiles will reference the Java EE platform, as defined by the JCP process, and may include a subset of Java EE platform technologies, additional JCP technologies not part of the base Java EE platform, or both. The expert group will also define the first version of a Java EE Web profile, a subset of the Java EE platform targeted at Web application development.

  • Pruning: Some technologies included in the Java EE platform are no longer as relevant as they were when they were introduced to the platform. There needs to be a way to "prune" these technologies from the platform in a careful and orderly way that minimizes the impact to developers still using these technologies, while enabling the platform to grow even stronger. As defined by that process, this expert group will consider technologies that should be marked for possible removal in a future Java EE platform specification. Possibilities include:

    • EJB CMP, effectively replaced by Java Persistence.
    • JAX-RPC, effectively replaced by JAX-WS.
  • SOA support: The Java EE platform is already widely used for SOA applications. As more and more enterprises realize the benefits of an SOA architecture, requirements on the platform have increased, both in terms of functionality and interoperability. Java EE 6 will need to consider additional Web services support. While basic Web services support is now part of the Java SE 6 platform, this specification will require newer versions of these technologies that provide additional Web services support. The Service Component Architecture (SCA) is defining facilities that could be used by composite applications in an SOA environment. The expert group is considering whether any of the SCA-defined facilities are appropriate for inclusion into Java EE 6 platform.

  • Other additions: The expert group proposed to include the following new JSRs in Java EE 6:

    • JSR-196 Java Authentication SPI for Containers.
    • JSR-236 Timer for Application Servers.
    • JSR-237 Work Manager for Application Servers.
    • JSR-299 Web Beans.
    • JSR-311 JAX-RS: Java API for RESTful Web Services.

Further updates are expected in these areas:

  • Enterprise JavaBeans.
  • Java Persistence API.
  • Servlets.
  • JavaServer Faces.
  • JAX-WS.
  • Java EE Connector API.

The exact set of technologies to be included will be determined by the expert group and will be based on partner and customer requirements. Some of those specs will also look at the rapidly emerging Web 2.0 space.


Conclusion

Java EE 5 is a strong, significant release, making it the most complete platform for enterprise development. Clearly, major steps have been taken to addresses most of the criticisms surrounding past Java development. EJB 3.0 and JPA are powerful and easy to use technologies, and the improvements in JAX-WS make Web service development easier than ever before.


Acknowledgements

The author thanks Jim Knutson and Russell Butek for their contributions to this article.

Resources

Learn

Get products and technologies

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Java technology, SOA and web services
ArticleID=242245
ArticleTitle=Get to know Java EE 5
publish-date=08252007