Here's what's new and what 1.4 will mean to you as a developer.
In October 2001, with publication of the J2EE 1.3 specification barely a month old, an expert group was already formed and beginning to work on J2EE 1.4. The Java 2, Enterprise Edition (J2EE) 1.3 specification had just come out the month before, introducing some major enhancements to the platform, such as Enterprise JavaBeans (EJB) 2.0, J2EE Connectors 1.0, and basic support for XML, but the platform was still missing some essential pieces. Java Server Pages (JSP) was increasingly criticized; the tools suffered from a lack of J2EE server management tools and from having only proprietary methods for deploying applications; no standards for third- party security product integration existed; the connector architecture supported only one way integration; and perhaps most important, the public at the time was immersed in feverish hype surrounding Web services, but there were no standards in the J2EE platform for implementing Web services.
J2EE 1.4, now in the Proposed Final Draft 2 stage and poised for final release this summer, solves many of the problems of J2EE 1.3 while maintaining portability and complementing the existing J2EE programming model. And despite the gloomy look back at J2EE 1.3, keep in mind that what we've witnessed is the normal evolution of any platform.
This article is an architect-level overview of the major new features added to the platform, and their implications. Minor tweaks to the JavaMail API and the Java Message Service (JMS) API just to name a couple exist in the specification, but I don't cover them in this article. For a full list of other changes and for a list of all the standards that must be implemented in a fully compatible J2EE 1.4 application server, see java.sun.com/j2ee. For now, I'm concerned only with the key innovations that architects should be aware of before they start implementing new enterprise applications, starting with support for Web services.
J2EE and Web Services Integration
The most visible change to the J2EE 1.4 platform is strong integration of Web services. J2EE components can now interact with Web services and implement them in a standard, portable fashion. The component specifications involved are:
WS-I (Web Services Interoperability Organization) Basic Profile
- Java API for XML Remote Procedure Calls (JAX-RPC)
- Java API for XML Parsing (JAXP 1.2)
- SOAP with Attachments API for Java (SAAJ 1.1)
- Java API for XML Registries (JAXR)
- Implementing Enterprise Web Services (JSR 109).
J2EE 1.4 now mandates that any compliant application server must support the WS-I Basic Profile 1.0, a specification that sets standard definitions of what Web services look like at the protocol and transport levels. The Basic Profile is not an API that you need to worry about; it's the application servers that need to adhere to it to ensure that their Web services implementations are fully interoperable with any other Basic Profile supporting Web services implementation.
JAX-RPC defines RMI-like interfaces for interacting with and implementing SOAP/HTML-based Web services in an RPC style. (Clients interact with methods on objects, not documents.) The JAX-RPC specification defines mappings from Java classes to the XML used in SOAP calls, abstracting the SOAP-over-HTTP plumbing from application code. The programming model is similar to RMI's; in fact, JAX-RPC Web-services interfaces must implement Java.rmi.Remote. JAX-RPC is used to implement the stubs J2EE components invoke when making calls to Web services; it also defines an endpoint model that enables Servlets and EJBs to be used to implement Web services. (See below, "Programming Model for Java Web Services.")
Inclusion of the JAXP 1.2 specification means that J2EE 1.4 application servers will now have XSLT engines, SAX 2.0, and DOM level 2 parsers included, out of the box. You can write your XML processing code once and swap in third-party parsers or XSLT engines as necessary, without changes to the source code. This is a step forward from J2EE 1.3, which included only JAXP 1.0, which did not support XSLT or the latest DOM/SAX technologies.
SAAJ 1.1 (Java.sun.com/xml/saaj/index.html) is a standard API and object model for producing and consuming SOAP 1.1 messages with MIME attachments. It can be used alone or in conjunction with JAX-RPC, depending on how far down developers want to delve into SOAP details. When used alone, SAAJ provides a mechanism for synchronous SOAP message transmission over HTTP.
JAXR 1.0 (Java.sun.com/xml/jaxr) defines a standard API and programming model for interacting with an XML-based registry, such as UDDI, ebXML, or OASIS. Like JAXP, JAXR allows you to swap registry providers behind the scenes without changing your code. Major application-server vendors, including Oracle, are bundling UDDI servers with their application servers, which will allow Web services deployed locally to be listed within the local registry.
It's worth noting that JAXR is a client API for interacting with other registries. It does not specify how or whether J2EE Web services should be exposed in a local registry in the same way that EJBs are exposed through JNDI . However, it does mandate that J2EE 1.4 servers ship with a JAXR provider and compatible registry, allowing developers to use vendor-specific ways to expose locally deployed Web services in the registry for the outside world to find.
Web Services for J2EE (JSR 109)
Whereas JAX-RPC, SAAJ and so on are the component APIs that enable Web services, JSR 109, also known as Web Services for J2EE, is the grand plan that defines how these specifications fit into the J2EE programming model.
As of J2EE 1.4, developers have a standard way to look up and invoke Web services as well as implement Web services by using either stateless session beans or plain Java classes (mapped to a Servlet). This is the bread and butter of the new Web services integration process. (A detailed look at the mechanics of using Web services in J2EE is provided below.)
To ensure that Web services written in J2EE are portable across containers, new packaging and deployment syntax and semantics such as the new webservices.xml file, which fully specifies all the details about a Web service, have been added. This file (and all generated Web-services container classes) is deployed with the WAR (if Servlets are used for Web services implementation) or within the EJB jar (if EJB is the chosen implementation technology.) Before J2EE 1.4, J2EE Web services were interoperable with other Web services but the code itself was not portable, because it relied on vendor-specific APIs or packaging/deployment mechanisms.
Another addition to the J2EE Web services story is the new Handler component. Handlers are developer-written components that can intercept SOAP calls before they reach a J2EE Web services implementation; they can also intercept the response to the call. Handlers act like Servlet filters, providing application code with direct access to incoming and outgoing SOAP messages. For example, handlers can be written that decrypt incoming SOAP invocations and encrypt their responses to give SOAP messages additional security for their trip across the wire.
Despite these improvements, the J2EE 1.4 Web services specifications are still missing syntax and semantics enhancements for supporting Web services transactions, security, asynchronous JAX-RPC calls, and other critical features such as workflow and basic guarantees of message reliability. These features have not yet been standardized by the public specifications such as SOAP and WSDL, on which the J2EE specifications are built. For example, it is not possible to execute or implement asynchronous Web services, because WSDL and SOAP do not define an asynchronous Web service (thus, neither can JAX-RPC). Also, WSDL does not define how to specify security or transaction semantics, and thus there are no standards upon which the J2EE spec can build portable APIs.
J2EE 1.4 upholds existing Web services standards in a clean way that takes advantage of the existing container and programming-model infrastructure. As Web services standards mature and features such as workflow and transactions are specified in WSDL, SOAP, and other Web service building-block APIs, we can expect to see support for these features in J2EE as well.
Other than Web services, the bread-and-butter changes in EJB 2.1 include important enhancements to EJB-QL, a new timer service, and the extension of message-driven beans (MDBs) to support any type of messaging system (not just JMS).
EJB QL, the query language introduced as part of EJB 2.0 in J2EE 1.3, now supports the ORDER BY clause a common SQL operation used by EJB developers to presort entity beans. Because the EJB 2.0 QL specifications did not include an ORDER BY clause, developers could not use this optimization and had to resort to expensive manual sorting algorithms. As a result, application server vendors such as BEA were quick to extend their own EJB implementations with this clause. With EJB 2.1, the ORDER BY clause is now officially supported; developers can use this clause to order the results of finders and selects, even selects of individual CMP fields.
EJB-QL has also been enhanced to include other basic aggregate functions available in SQL, such as AVG, COUNT, MAX, MIN, MOD, and SUM.
The new timer service in EJB 2.1 addresses a long-time need in the platform: execution of business logic at prescheduled times or intervals. Before EJB 2.1, developers had to use proprietary solutions, or operating-system-specific scheduling mechanisms such as CRON to execute business logic at prescheduled times or intervals.
The EJB 2.1 timer service builds a standard scheduling system directly into an application server. Any EJB type session, entity, or message-driven can create a timer that, upon expiration, causes the container to invoke a new EJBTimeout() method on the EJB, where scheduled business logic can reside. Timers can be configured to go off at regular intervals or at a specific date in the future. In the case of an entity bean, timers are actually associated with particular instances of an entity bean, identified by primary key. This is in contrast to session- or message-driven beans, for which a timer going off is fulfilled by any free bean in the pool.
A major and well-thought-out change in EJB 2.1 is that MDBs have been extended to support any message type. In contrast to EJB 2.0, in which MDBs responded only to JMS, EJB 2.1 MDBs can now be configured to respond to messages of any type. This allows architects to "plug in" any proprietary messaging provider they choose and have incoming asynchronous messages handled by business logic written to the MDB programming model.
Although developers still have the option of using JMS MDBs (J2EE application servers have been required to have a JMS implementation since J2EE 1.3), it's now possible to support new types of messages by adding a J2EE Connector resource adapter (usually provided by the vendor) that translates incoming messages into calls to the MDB. For example, it's now possible to write a resource adapter that accepts messages from your proprietary code running within your Oracle database. If a database wanted to notify J2EE logic about a table update (perhaps to maintain a middle-tier cache), the message would be sent in the user-defined proprietary format and be received by the adapter, which would parse and forward the incoming message to business logic in an MDB (a clean form of integration!).
The Servlet 2.4 specification is primarily a maintenance release with some clarifications and minor improvements, including portable logout, access to more request information, new lifecycle listeners, new filter techniques, and deprecation of the SingleThreadModel interface.
The Servlet 2.3 specification did not clearly define the semantics of being logged in or logged out of an application. This was important to applications that used the container-managed security/authentication features of the Servlet specification, because different Servlet containers each had their own interpretation of what exactly triggers a logout, affecting application portability. This approach has been clarified in the Servlet 2.4 specification, which provides an exact definition of logging out semantics.
Some small but useful additions to the specification include new methods for accessing data from a Web request. Specifically, a Servlet that has been invoked by another Servlet using the forward method of RequestDispatcher now has access to the "path" of the original request. Also, new methods have been added to the ServletRequest interface and ServletRequestWrapper interfaces that can retrieve the IP address, name and port of the local server in which a Web request has been received, as well as the address of the client that sent the request.
The Servlet 2.4 specification adds new listeners for Servlet requests, allowing application code to be notified when an incoming request is being serviced and when attributes have been added to, removed from, or replaced in from the ServletRequest. (The 2.3 specification supported these listeners only for changes to the ServletContext and HTTPSession.) The 2.4 specification also mandates that errors that occur within user-written listener/handler classes should propagate back to the client, excluding certain types of exceptions that occur concurrently with application code.
Servlet filters can now be configured to apply to RequestDispatcher forward() and include() calls, not just requests coming directly from the client. The Servlet 2.3 specification allowed filters to apply only to client requests.
Perhaps the most significant change, however, is the deprecation of the SingleThreadModel interface. The Servlet expert group felt that it does not adequately solve thread safety issues; even with a Servlet marked with the SingleThreadModel interface, session attributes and static variables can be accessed by multiple requests on multiple threads at the same time. The Servlet 2.4 specification now recommends that developers find other means to resolve threading issues, such as not using instance variables, or using synchronizing blocks. For complete details about other minor tweaks, fixes, and clarifications in Servlet 2.4, see java.sun.com/products/servlet.
JavaServer Pages 2.0 (JSP 2.0)
The JSP 2.0 specification brings much needed enhancements to the platform, including an expression language, simpler ways to write custom tags, JSP fragments, dynamic attributes, strong XML support, and better configurability.
JSPs have come under a lot of fire in the past, because developers were forced to use scriptlets to do simple things, such as traversing an object graph to print an attribute or using a Boolean expression. The advent of tag libraries gave developers a way to wrap such functions behind taglibs, but the development and maintenance cost of taglibs for essentially trivial functions is high.
With JSP 2.0 comes an expression language that finally delivers on the promise of removing code from the presentation layer. The expression language is a simple scripting language that allows developers to perform many operations without resorting to scriptlets. For example, the scriptlet
can be replaced via the expression language with the more elegant phrasing
The expression language in JSP 2.0 is also in JSTL (JSP Standard Tag Library). The Java Server Faces expert group (JSR-127: www.jcp.org/en/jsr/detail?id=127) is considering adopting this scripting language in its specification.
Simplified custom tag development: In JSP 1.2, both the semantics and the API for developing custom tags were complex. The result was that Web developers always had to write Java code to handle custom tags, even if the tag consisted only of HTML. With JSP 2.0, Simple Tag Extensions make it as easy to write a custom tag as it is to write a plain JSP page. You can now author custom tags in two new ways, by writing either
- A Java class that extends the new SimpleTag interface. This approach has a simpler API than classic tags and is not tied to the Servlet API. Simple tags are not cached between uses (as was the classic tag handler).
- A tag file a text file in which you can place a fragment of JSP code (that can just be plain HTML), which you can then reuse as a custom tag throughout your application. For example, say you have a 20-line block of JSP/HTML that you need to reuse, which also has placeholders for attributes passed in at runtime. In JSP 1.2, you'd have to add the HTML block to a tag handler written in Java. In JSP 2.0, the tag handler can be written in JSP, thereby simplifying development and maintenance.
JSP fragments are a new option for developers using simple custom tags. Attributes defined for custom tags now have an element called fragment, which, when marked true, can force the attribute to be evaluated by the tag handler at runtime, rather than by the container at the tag's first initialization.
Dynamic attributes: Custom tags can accept new attributes dynamically at runtime, and the names of these attributes don't have to be defined in advance, as they did under JSP 1.2.
JSP configuration: The options available for configuring JSP files in web.xml have also been beefed up. JSP 2.0 has a new <jsp-properties-group> element that allows developers to configure groups of JSPs identified by a URL pattern. Two examples of configuration items a developer might apply to a particular set of JSPs are the new <include-prelude> and <include-coda> elements, which define a custom header (a file with JSP/HTML code in it) and footer, respectively, that the JSP engine will automatically include at the top or bottom (or both) of a JSP. I'm not sure what the intention is behind these new elements especially because the OpenSymphony Sitemesh and Struts Tiles projects already exist and do a much better job.
Java Authorization Contract for Containers
With J2EE 1.4, developers will have more choices when it comes to choosing security infrastructure providers, thanks to the much-needed Java Authorization Contract for Containers (JACC). JACC provides a standard contract between J2EE 1.4 servers and third-party authorization service providers (as well as integration between the J2EE authorization model and the J2SE security model), allowing these products to implement the role-based authorization models defined in the Servlet and EJB specifications.
This innovation means that you will have more choices when it comes to choosing security infrastructure providers. These providers will be able to integrate their functionality into J2EE 1.4 application servers transparently, allowing J2EE application code to remain portable.
J2EE Management 1.0
In terms of platform maturity, the new management and deployment specifications are the most important additions to J2EE 1.4 because they will have a significant effect on the tools market.
The J2EE Management 1.0 specification identifies the J2EE application server resources that can be managed and how they can be managed. The specification provides standard ways to explore every aspect of an application server, right down to the deployed entity bean and the full contents of its deployment descriptor. Events can be set up for managed resources that will notify management software when preset criteria are matched. A state management feature allows management programs to perform health checks on any part of a J2EE system to determine whether managed resources have failed or are running, and how long they've been running. The management software can also stop and restart resources automatically.
Finally, comprehensive performance statistics factors such as how many times a particular method has been called, the maximum amount of time taken to complete a method invocation, how many EJB instances are in the ready pool, and so forth can be monitored and recorded.
Developers and tool vendors can now interact with managed resources through a standard management EJB component, which is the entry point for accessing a rich-object model of JMX-managed resources. These Java Management Extensions (JMX) objects are the programmatic interfaces used to manage and monitor an application server and its deployed components.
For tools not written in Java, J2EE Management 1.0 provides mappings to traditional management protocols and interfaces, such as Common Information Model (CIM), and to a Simple Network Management Protocol (SNMP) Management Information Base (MIB). The CIM and SNMP MIB specify standard protocols and interfaces for managing enterprise resources. This means that the standard management tools in use at various large companies will also be able to manage J2EE application servers, an important ability for companies with large data centers.
The J2EE management specification should open up the management tools market to J2EE developers. Even though we can expect to see a range of management products that can monitor any J2EE 1.4-compliant application servers, it's also likely that sophisticated developers will implement their own management consoles to provide fine-grained monitoring and control over their deployed applications.
J2EE Deployment 1.1
Every J2EE server has its own proprietary mechanism for deploying an application. In some cases, integrated development environments (IDEs) have been extended with application server-specific capabilities for deploying an application. For example, JBuilder supports the automatic deployment of a JBuilder application written to WebLogic. For those who do not tie their build-and-deploy process to an integrated development environment, ANT is typically used, but ANT scripts must be painstakingly customized to each server that must be supported.
The new J2EE deployment specification in J2EE 1.4 provides standard APIs for deploying J2EE applications on any J2EE 1.4-compliant server in a standard way. It lets you write server-agnostic ANT scripts or IDEs with universal application server support. Users of these new tools will benefit from the ability to deploy an application on any J2EE 1.4 application server, configure the deployed application, and un-deploy the application all without the necessity of vendor-specific hooks.
J2EE Connectors 1.5
The new J2EE Connectors 1.5 specification greatly enhances the integration capabilities of J2EE 1.4, with new bidirectional communication that has two-way transaction propagation, a new work/threading feature, and standards for packaging/deploying resource adapters.
The new bidirectional communication feature allows an enterprise information system (the non-J2EE system you are trying to connect with, also known as an EIS) to asynchronously communicate with EJBs in a J2EE application server. This is in addition to the J2EE-to-EIS communication that the Connectors 1.0 specification mandated.
When the EIS sends a message to the Connector's Resource Adapter (RA), Connector infrastructure and hooks are provided to automatically deliver calls to MDBs that have registered as listeners via entries in MDB-deployment descriptors. The Connector specification recommends that developers use MDBs as dispatchers for parsing messages from an EIS and making calls to business logic residing in the same MDB or in other session or entity beans in their application server. The cool thing about invoking EJBs with an EIS is that the RA can import transactions from the EIS, allowing business logic running in the application server to take part in a use case initiated from the EIS, in an atomic (all or nothing) fashion.
Whereas 1.0 connectors were limited to acting as one-way wrappers for an EIS, the new bidirectional feature opens the door for J2EE to become a full-fledged EAI platform.
A standard packaging-and-deployment model for RAR (Resource Adapter Archive) files has also been standardized for J2EE 1.4, allowing developers to deploy an RA in a standard way across application servers, instead of requiring vendor-specific configuration/bootstrap techniques.
Finally, a multithreading capability has been introduced. RA authors can now create and submit Work instances to an application server. The application server executes and manages the lifecycle of this separate thread, which can perform work (concurrently) on behalf of the RA. This addition enables better scalability for RA, which can now respond to requests from an EIS and immediately delegate the work of processing the requests to new Work instances that run in the background similarly to how Web servers listen on port 80 and then immediately spawn new threads to handle processing of an incoming request.
Ready For Web Services?
J2EE 1.4 provides the groundwork for Web services development with J2EE, as well as important tool enhancements, new standards for application deployment and server management, and a pluggable authorization facility.
Significant programming model changes include the new expression language and simplified tab library development model in JSP, as well as the new timer service and QL enhancements in EJB 2.1. Integration has received a major face-lift, with two-way communication support in the J2EE Connectors specification and message-type independent MJBs.
The final release of the platform was scheduled to ship in Q1 but was delayed by the addition of the WS-I Basic Profile as a requirement for J2EE 1.4-compliant application servers. The decision ensures that J2EE Web services will be fully interoperable, but the final release of the platform won't ship until this summer, after the final version of the Basic Profile is released. Sun has publicly stated that there won't be any new features added to J2EE 1.4 between now and the final release, other than minor clarifications/bug fixes. Luckily, many vendors, including Oracle, have already begun supporting some of the new J2EE 1.4 standards, including EJB 2.1 and some of the Web services APIs.
Application code in a J2EE environment can easily invoke foreign Web services by using the client-access model defined for J2EE 1.4. The model is actually quite similar to how one might look up EJBs. Although how the actual interface to a Web service is found can vary (depending on whether the WSDL interface is known at development time or not), the general flow is as follows:
A client uses JNDI (Java Naming and Directory Interface) to look up a Web-service-specific service object (which, by definition, implements the Java API for XML Remote Procedure Calls, or JAX-RPC, Service interface). Conceptually similar to an EJBHome, the service object is used to get an instance of a client-side stub (or proxy) to a remote Web service (such as an EJBObject). The stub implements a Web service-specific business interface, which has to extend the Java.xml.rpc.Service interface. Clients can then make invocations on business methods on the Web services stub while, behind the scenes, their method calls are being converted to SOAP documents, marshaled over HTTP, received on the other end, and executed.
J2EE 1.4 includes standards for how to implement stateless Web services by using existing infrastructure provided by the Servlet and EJB specifications. In both cases, the first step is to write a Service Endpoint interface, a normal Java interface that implements Java.rmi.Remote and defines the business methods that will be exposed as a Web service. This interface can also be generated from an existing WSDL file by container-specific tools. With the Service Endpoint interface at hand, either stateless session beans or a plain Java class (which will be mapped to a Servlet) can be used to implement the methods from this interface.
In the EJB case, the bean class and Remote interface must implement (but are not limited to) the methods defined on the service interface. Other than some other minor restrictions and packaging details, that's basically all you need to use an EJB to implement a Web service. When the service has been implemented, the deployment step involves executing a vendor-specific deployment tool that will generate container plumbing that maps SOAP/HTTP calls to invocations on the bean class, much like the familiar EJBc tool in an EJB context.
In the plain Java-class case (Servlets), the class can also directly implement the service interface, or at least implement the business methods described in it. Because plain Java classes do not have a way to track their lifecycles (such as EJBCreate/Remove()), an optional ServiceLifeCycle interface can be implemented that provides init/destroy methods. The init method also passes in a ServletEndpointContext object, which gives application code access to container resources such as the ServletContext and HTTPSession. Furthermore, plain Java classes can designate themselves as multithreaded or single-threaded by implementing the Javax.servlet.SingleThreadModel interface, just as a Servlet would.
During the deployment step, the container generates or provides a Servlet that is associated with the plain Java class. The Servlet parses incoming SOAP/HTTP calls and maps them to the plain Java class that implements the business logic defined in the service interface.
This article was originally published in April 2003 by Oracle Technology Network (http://otn.oracle.com)