EJB 2.1 Web Services: Part 1: Monson-Haefel's Guide to Enterprise JavaBeans

Java Development News:

EJB 2.1 Web Services: Part 1: Monson-Haefel's Guide to Enterprise JavaBeans

By Richard Monson-Haefel

01 Aug 2002 | TheServerSide.com

Introduction

Richard Monson-Haefel is the author of Enterprise JavaBeans, 3rd Edition, Java Message Service and one of the world's leading experts on Enterprise Java. He is co-founder of OpenEJB, an open source EJB container used in Apple Computer's WebObjects, and an independent consultant.

The driving force behind EJB 2.1 is the need for Enterprise JavaBeans technology to support Web services -- a need that in turn is driven by Microsoft's release of its mammoth .NET platform, which is a significant threat to J2EE, and to Java technology in general. Support for Web services is embodied in three new APIs:

  • JAX-RPC (Java API for XML-RPC) is basically Java RMI over SOAP; it provides a remote interface for RPC-style SOAP messaging.

  • SAAJ (SOAP API with Attachments for Java) is an API that models the structure of a SOAP message and also has some limited message-delivery capabilities.

  • JAXM (Java API for XML Messaging) is similar to JMS (Java Message Service); it provides a robust messaging infrastructure for sending and receiving SOAP messages.

This month's column is the first of two installments on EJB 2.1 Web services. It provides a high-level primer on Web services, then goes on to an overview of JAX-RPC and the new EJB endpoint interface. In next month's column I'll tell you about SAAJ and JAXM.


Understanding Web Services

Web services represent the latest wave in distributed computing and perhaps the most important innovation since the introduction of Java in 1995 and XML in 1998. Although the term "Web services" is bantered about quite a bit, arriving at a concrete definition is difficult because Web services is, at the highest level, not specific to any particular technology or platform. It's often defined in fairly abstract terms like "a substrate for building distributed applications using software running on different operating systems and devices"1 or "self-contained, self-describing, modular applications that can be published, located, and invoked across the Web"2. Of course these quotes are taken out of context, but that's the essential point: You need some kind of context to define Web services.

The following is a definition of Web services that has meaning in the context of J2EE, EJB, .NET and most other Web services platforms:

Web services are network applications that use SOAP and WSDL to exchange information in the form of XML documents.

To understand this definition, you need to understand SOAP and WSDL. The following are brief definitions of these terms.

  • XML
    The eXtensible Markup Language (XML) is a recommendation of the W3C (World Wide Web Consortium) that defines the rules for creating XML markup languages. An XML markup language is a set of tags (called elements) that are used to describe information in Unicode text and organize it hierarchically. Markup languages (a.k.a. XML grammars) can be described using XML Schema. A text document that adheres to the rules described by an XML grammar is called an XML instance. XML technologies are ubiquitous, and are often employed in the exchange and storage of application data, and to organize literary documents.

  • SOAP 1.1
    SOAP (Simple Object Access Protocol), an XML grammar developed by Microsoft, IBM, and others, is currently under the auspices of the W3C. It's an application protocol used in both RPC and asynchronous messaging. SOAP is very flexible and extensible and unlike its predecessors (DCE RPC, CORBA IIOP, Java RMI-JRMP, and DCOM) it's been endorsed and adopted by just about every major vendor.

  • WSDL 1.1
    Web Service Description Language, is also an XML grammar, developed by Microsoft and IBM under the auspices of the W3C. Its an XML-based IDL (Interface Definition Language) which can be used to describe Web services, including the kind of message format expected, the Internet protocol used, and the Internet address of the Web service.

In essence, Web services represent a new distributed object technology similar to CORBA IIOP and Java RMI, but with some critical differences. The primary difference is that Web services are, in my opinion, truly platform-independent. Although Java RMI and CORBA IIOP make the same claim, in fact these older technologies require their own platforms. To use Java RMI you need a Java virtual machine and the Java programming language. For developers working in other languages, such as Visual Basic or C++, Java RMI is not platform-independent. CORBA IIOP is also restrictive, because the IIOP protocol usually requires an elaborate infrastructure like a CORBA ORB, which limits developers to those few vendors that support CORBA, or to the Java environment (which includes built-in support for CORBA IIOP).

Web services, on the other hand, are not tied to a specific platform like the JVM or to a technology infrastructure like CORBA because they focus on the protocols used to exchange messages -- SOAP and WSDL -- not the implementation that supports those protocols. In other words, you can build Web services on any platform, using any programming language anyway you please.

Another advantage of Web services over other distributed object systems is that they are based on an existing technology infrastructure and are therefore easier for vendors to implement. SOAP and WSDL are based on XML, for which widespread support already exists, in the form of XML parsers. XML parsers are available for just about every modern programming language (Java, C, C++, C#, VB, Perl, Python, etc.), so the infrastructure for processing SOAP messages and WSDL documents already exists. In addition, Web services messages are normally exchanged over TCP/IP, which is supported by just about every modern software platform and programming language available today. Because Web services builds on an existing infrastructure of XML and TCP/IP, adoption of Web services has been quick and widespread. In fact, more than 70 Web service SOAP toolkits are already available for a large variety of programming languages and environments, including Java, JavaScript, C, C++, VisualBasic, Delphi, Perl, Python, Ruby, SmallTalk, .NET, and others3.


SOAP Toolkits: API- vs. Stub-based Toolkits

A SOAP toolkit is an API used to send and receive SOAP messages. As a protocol, SOAP defines the structure of messages, but it doesn't define the implementation of SOAP toolkits. I already mentioned that there are literally dozens of SOAP toolkits in many different programming languages including Java, C and C++, C#, VB.NET, Perl, etc. The proliferation of SOAP toolkits is at once mind-boggling and encouraging, because it indicates how easy it is to write APIs to the SOAP standard.

Each toolkit defines its own programming model, and they're all slightly different. Some toolkits model the structure of SOAP messages, with objects like Envelope, Header, and Body, while others adopt the RPC stub programming model, which makes a Web service look like a procedure or method call. The SOAP toolkits that model the structure of a SOAP message can be categorized as API-based toolkits, while SOAP toolkits that use RPC stubs can be called stub-based toolkits4.

Stub-based toolkits are rooted in the traditional RPC programming model. They use an RPC stub to communicate with a Web service. They make a Web service appear, from the perspective of the client, to be an object with methods. JAX-RPC (Java API for XML-RPC) is the standard stub-based programming model of Enterprise JavaBeans 2.1.

SOAP API toolkits are used to construct a SOAP message explicitly, using complex types like structs or objects, which model parts of a SOAP message (Envelope, Header, Body, etc.) and XML tree-based APIs like the W3C's DOM (Document Object Model). SAAJ (SOAP with Attachments API for Java) is the standard SOAP API in EJB 2.1. It provides an object-oriented API for constructing SOAP messages based on an Abstract Factory pattern5. SAAJ can be used alone, but is often used in combination with JAXM (Java API for XML Messaging), which communicates with Web services by using SAAJ to model outgoing and incoming SOAP messages.


WSDL and SOAP Toolkits

Regardless of the toolkit used to generate and exchange SOAP messages, WSDL defines, in a platform- and toolkit- independent format, how SOAP messages are structured and exchanged.

When using an API-based SOAP toolkit like those that rely on SAAJ and JAXM, a client developer will treat the WSDL document as a guide to constructing and exchanging SOAP messages. In this case, the developer must be able to read and understand the WSDL document. WSDL tells the developer the encoding style, the XML namespaces employed, which elements to use in the SOAP Body and Header elements, etc.

When developers of a client application use a stub-based toolkit like JAX-RPC, they will use a vendor-supplied stub-generating tool. The stub-generating tool reads the WSDL document and automatically generates the stub and remote interface (see Figure 1). The remote interface name, its methods, and their parameters are all derived directly from the WSDL document. The stub would also be derived from the WSDL document, and would implement the protocol (e.g., HTTP), encoding style, and Internet address described in the WSDL document.


Figure 1 - Generating a stub from WSDL


Wrapping Up

I'm writing two books that cover the latest in  J2EE Web services: Enterprise JavaBeans, 4th  Edition (O'Reilly), and J2EE Web Services  (Addison-Wesley). They won't be available  until early 2003, however. If you would like  to be notified when they are published, please  send an e-mail to Book-Notification@Monson-Haefel.com.

Obviously there is a lot more to Web services than this short primer can cover. If you are interested in learning more, a number of books cover various aspects of Web services, from SOAP to WSDL. For an overview, the best book on Web services I've read so far is Understanding Web Services by Eric Newcomer (Addison-Wesley 2002) -- but to be honest I haven't read that many, so look at other titles as well. Unfortunately, all the Web services books you'll find on the bookshelf today will be out of date by the end of this year. Both SOAP and WSDL will be updated to new versions and the EJB 2.1 and J2EE 1.4 Web services specifications aren't yet final. Most Java Web services books today cover Apache SOAP or Apache Axis (a very good platform) but fail to provide much coverage of J2EE Web services, if any -- not surprising when the specification is still being drafted. The good news is that most books will probably be updated and new books will be published to cover the latest specifications and trends in Web services.


JAX-RPC and EJB 2.1

In the July installment of this column I explained that JAX-RPC is essentially Java RMI over SOAP. Each EJB vendor will provide its own implementation of JAX-RPC, but the differences will be minor because all implementations must adhere to the JAX-RPC specification. JAX-RPC can be used as a client API to gain access to other Web services, but it's also the foundation for a new type of enterprise-bean interface called the endpoint interface, on a par with the local and remote interface types.


JAX-RPC as a client API

As a client API, JAX-RPC can be used from session, entity, or message-driven beans to exchange SOAP messages with Web services on any platform. JAX-RPC defines three programming models: generated stub, dynamic proxy, and the DII (Dynamic Invocation Interface). While I discuss all three models below, you're most likely to use generated stubs in EJB development.


Generated Stubs

If you are to use JAX-RPC to access a Web service, the Web service must publish a WSDL document. The JAX-RPC toolkit, which is provided by the EJB vendor, generates Java RMI interfaces and stubs that implement the Web service operations described by the WSDL document. Once stubs and interfaces are generated you can bind them to the JNDI ENC (Environment Naming Context) of any enterprise bean and use them to communicate with those Web services. In this model, the stubs are generated at deployment time (see Figure 2).


Figure 2 - JAX-RPC generated stub sequence diagram


WSDL describes the interfaces to Web services as ports; each port may have one or more operations. Ports and operations are analogous to Java interfaces and methods, respectively. In fact, JAX-RPC defines a mapping between WSDL and Java RMI that generates remote interfaces from ports, with methods that correspond to port operations. For example, a WSDL document might describe a port called BookPrice with a single operation called getBookPrice. The following is an abbreviated listing of the BookPrice WSDL document:


<?xml version="1.0"?>
<definitions name="BookPrice"
             targetNamespace="http://www.xyz.com/GetBookPrice"
   xmlns:tns="http://www.xyz.com/GetBookPrice"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns="http://schemas.xmlsoap.org/wsdl/">

<!-- message elements describe the paramters and return values -->
<message name="IsbnMessage">
   <part name="isbn" type="xsd:string" />
</message>
<message name="PriceMessage">
   <part name="price" type="xsd:float" />
</message>

<!-- portType element describes the abstract interface of a Web service -->
<portType name="BookPrice">
  <operation name="getBookPrice">
     <input name="isbn" message="tns:IsbnMessage"/>
     <output name="price" message="tns:PriceMessage"/>
  </operation>
</portType>

<!-- binding goes here -->

<!-- service tells us the Internet address of a Web service -->
<service name="BookPriceService">
  <port name="BookPrice" binding="tns:BookPrice_Binding">
     <soap:address location="http://www.xyz.com/BookPrice" />
  </port>
</service>

</definitions>

At deployment time a JAX-RPC stub-generating tool converts the WSDL port into a corresponding remote interface and stub, and creates a factory for accessing that stub, based on the service definition. The port and service interfaces would look like these examples:


public Interface BookPriceService extends javax.xml.rpc.Service{

    public BookPrice getBookPrice( ) throws RemoteException;

}

public Interface BookPrice extends java.rmi.Remote {

    public float getBookPrice(String isbn)
        throws RemoteException;

}

This is a fairly simple example; the service has only one port. In practice a service may have many ports, each with a corresponding remote interface and stub.

Once the interface and stub have been generated and bound to the JNDI ENC, they can be used at run time to invoke operations on the Web service. In the listing below a stateless session bean, the BookCatalog EJB, uses JAX-RPC to look up the wholesale price of a book from a .NET Web service.


public class BookCatalog implements javax.ejb.SessionBean {
    ...
    public float getWholeSalePrice(String isbn) {
       try {
   
          InitialContext jndiContext = new InitialContext ( );

          BookPriceService service =
          jndiContext.lookup("java:comp/env/service/BookPriceService");

          BookPrice bookPrice_port = service.getBookPrice();

          float price = bookPrice_port.getBookPrice( isbn );
          return price;

       catch(RemoteException re){
           // handle remote exception
       }catch(ServiceException se){
           // handle service exception
       }catch(NamingException ne){
           // handle naming exception
       }
    }
    ...
}

When the getBookPrice() method is invoked, the JAX-RPC stub sends a SOAP message to the Web service, in this case a .NET program. The SOAP message generated by the stub would look like this.



<?xml version='1.0' ?>
<env:Envelope
 xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xyz='http://www.xyz.com/BookPrice"
 encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <Body>
      <xyz:getBookPrice>
          <isbn xsi:type="string">1565928695
      </xyz:getBookPrice>
   </Body>
</env:Envelope>


The .NET Web service then processes the SOAP message and sends a response back to the stub. The stub extracts the result from the SOAP message and returns it to the client (See figure 3).


Figure 3 - JAX-RPC invocation loop


The methods in JAX-RPC stubs can have arguments that are primitive types (int, long, etc.), primitive wrappers (java.lang.Integer, java.lang.Long, etc.), arrays, a few standard Java types (e.g., String and Date), and custom object types. Custom object types must adhere to rules defined in the JAX-RPC specification. These rules are not that restrictive: They prohibit references of type java.rmi.Remote and require that the objects be serializable to XML according to conventions prescribed by JAX-RPC.


Dynamic Proxy

In addition to the generated stubs illustrated above, JAX-RPC also supports dynamic proxies. A dynamic proxy is used in the same way as a generated stub, except its remote interface and stub implementation is generated dynamically at run time. If you're familiar with the Proxy architecture of the Java Reflection API, than the dynamic JAX-RPC will make sense to you. The next example is of a stateless session bean that JAX-RPC to create a dynamic stub:


public class BookCatalog implements javax.ejb.SessionBean {
    ...
    public float getWholeSalePrice(String isbn) {
       try {
   
          InitialContext jndiContext = new InitialContext ( );

          javax.xml.rpc.Service service =
          jndiContext.lookup("java:comp/env/service/DynamicService");

          BookPrice bookPrice_port = service.getPort(BookPrice.class);

          float price = bookPrice_port.getBookPrice( isbn );
          return price;

       catch(RemoteException re){
           // handle remote exception
       }catch(ServiceException se){
           // handle service exception
       }catch(NamingException ne){
           // handle naming exception
       }
    }
    ...
}

At run time the getPort() method automatically maps the BookPrice interface to a corresponding port definition in the WSDL document, then generates a stub that implements that interface.


The DII

JAX-RPC also supports another, even more dynamic API, named the DII (Dynamic Invocation Interface). The DII allows the developer to assemble SOAP method calls dynamically at run time. If you've used the CORBA Dynamic Invocation Interface, the JAX-RPC DII will seem familiar. The JAX-RPC DII resembles Java Reflection in that it enables you to get a reference to an object that represents a single Web service operation, in the form of a method, and to invoke that method without needing to access the service factory or to use a stub and a remote interface. For example the following listing shows the same enterprise bean accessing the getBookPrice() operation of the BookPrice port.


public class BookCatalog implements javax.ejb.SessionBean {

    ...
    public float getWholeSalePrice(String isbn) {
       try {
   
          InitialContext jndiContext = new InitialContext ( );

          javax.xml.rpc.Service service =
          jndiContext.lookup("java:comp/env/service/DynamicService");

          QName port = new QName("http://www.xyz.com/GetBookPrice ","BookPrice");
          QName operation = new QName("http://www.xyz.com/GetBookPrice",
                                      "getBookPrice");

          Call callObject = service.createCall(port, operation);

          Object [] args = new Object[1]; args[0] = isbn;

          Float price = (Float) callObject.invoke( args );

          return price.floatValue();

          }catch(JAXRPCException se){
           // handle JAX-RPC exception
          }catch(NamingException ne){
           // handle naming exception
          }
       }
    }
    ...
}

You can actually configure -- at run time -- the parameters, invocation style, encoding, etc. Everything you can configure statically with WSDL you can configure dynamically with the DII.

While the DII is certainly useful for self-organizing systems, the majority of EJB developers will use generated stubs for access to Web services. In most cases, they'll know in advance the Web services and specific operations they'll be accessing. When generated stubs are so simple, why bother with anything as complicated as the DII?

One of the gray areas associated with using the dynamic proxies or DII is how the service locates the WSDL files. EJB 2.1 doesn't address this concern, so it's likely that each vendor will need to provide extensions for declaring the whereabouts of the WSDL files used to generate dynamic proxies or DII Call objects.


JAX-RPC and the endpoint interface

Since JAX-RPC is simply another flavor of Java RMI, it seems natural to use it to access enterprise beans, which you can already access using Java RMI-IIOP and proprietary flavors of Java RMI. Using JAX-RPC to talk to EJBs implies that EJBs can act as Web services, and they can - at least, stateless session beans can. EJB 2.1 permits you to use JAX-RPC only with stateless session beans, because SOAP is a stateless messaging protocol - it has no notion of object identity, so it can't be used with stateful or entity beans.

EJB 2.1 defines a new Web service endpoint interface for stateless session beans. Folks in the world of Web services use the term "endpoint" for anything that sends or receives SOAP messages. In EJB an endpoint is a stateless session bean that can be accessed via SOAP, and that follows the mapping rules for Java-to-WSDL and Java-to-SOAP specified by the JAX-RPC specification. Using JAX-RPC as the basis for EJB endpoints makes sense, because the JAX-RPC specification defines detailed rules for marshaling between SOAP messages and Java method calls as well as generating WSDL documents from Java remote interfaces (and vice versa).

Unlike the remote and local interfaces familiar to EJB developers, the endpoint interface does not extend an EJB Object type (i.e., EJBObject or EJBLocalObject). Instead, the endpoint interface extends the javax.ejb.Remote interface directly. For example, the BookPrice Web service, used in earlier examples, could easily be implemented as an endpoint in EJB. The following shows an endpoint interface for BookPrice, and a partial listing of the stateless session bean that is the implementation of the Web service:


public interface BookPrice extends javax.rmi.Remote {

     public String getBookPrice(String isbn) throws javax.rmi.RemoteException;

}

public class BookPriceWS implements BookPrice, javax.ejb.SessionBean  {

     public float getBookPrice(String isbn){

        Connection con = null;
        Statement stmt = null;
        ResultSet rs;
        try {
            DataSource ds = jdniEnc.lookup("java:comp/env/jdbc/DataSource");
            con = ds.getConneciton();
            stmt = con.createStatement();
            rs = stmt.executeQuery("SELECT wholesale FROM CATALOG WHERE isbn = '"
                                    +isbn+"'");
            if(rs.next()){
              float price = rs.getFloat("wholesale");
              return price;
            }else{
              return 0;// zero means its not stocked.
            }
        }
        catch (SQLException se) {
            // handle SQLException
        }
     }

     ...
}

One nice advantage endpoints have over remote and local interfaces is that they don't carry extra baggage in the form of unused methods of EJBObject or EJBLocalObject so the enterprise bean class can implement the endpoint interface without a problem. (Note: you don't need to declare the RemoteException in the bean class methods because implementations can implement a subset of the exceptions an interface declares.)

In addition, an endpoint does not include a home interface. SOAP doesn't specify support for pass-by-reference, so you can't ask one Web service interface (a home interface) to pass you a reference to another (a remote interface). Furthermore, you can't create or remove a Web service. For these reasons a home interface is unnecessary.

When developing a Web service as a stateless session bean, you first define the endpoint interface, then use it to generate the JAX-RPC client stubs, a WSDL document or, both If you generate the JAX-RPC client stub, you can package it with a J2EE client JAR and, without any modification, use it to access the stateless session bean, using SOAP as the protocol. This tactic works best when you use the same brand of EJB server to deploy both the client and the beans. If you generate a WSDL document from the endpoint interface, other SOAP toolkits can use the document to access your stateless bean. WSDL and SOAP are the lingua francas of Web services, so publishing a WSDL for an EJB Web service allows for interoperability with other platforms.


Figure 4 - Using SOAP to access a stateless session bean


As I mentioned briefly, there are some limitations to an endpoint interface that are unique to Web services. For one thing, pass-by-reference is not allowed. One consequence is that a method argument may not be a remote reference type that implements the javax.rmi.Remote interface. This restriction exists because distributed computing pass-by-reference is inherently complicated. It requires specifications for marshalling references and the realization of those references into programmatic constructs (stubs), which raises implementation issues.

In addition to the ban on pass-by-reference, the rules for endpoint interfaces require that methods accept as arguments only primitive, array, and serializable objects. An interesting implication is that pass-by-value (a.k.a. pass-by-copy) is supported for any custom type. For example, if you define your own serializable Address class, that type may be a parameter of an endpoint method. Standard Java types like String, Date, Calendar, BigInteger, and BigDecimal are also supported.

A few different messaging styles and protocols can be used with SOAP and documented by WSDL. These include RPC/encoded, document/literal, RPC/literal, and even document/encoded. JAX-RPC vendors are required to support RPC/encoded and document/literal; other styles are not addressed.

When you use document/literal, the parameter to the endpoint method is an XML document, represented by a special type called SOAPElement. This type is part of the SAAJ (SOAP API with Attachments for Java), an API that models the structure of the SOAP message. The SOAPElement parameter of a document/literal JAX-RPC method represents the XML document carried by the SOAP Body element -- but that begins to take us beyond the scope of this article. In most cases EJB developers will use RPC/encoded messaging style, but document/literal is available if needed.


Final Words

Web services represent a paradigm shift in distributed computing. They emphasize protocols rather than implementations -- a departure from legacy technologies like CORBA, DCOM, and Java RMI. As a result the Web services model will, in my opinion, be more widely accepted and broadly implemented than its predecessors.

The wave of support for Web services sweeping the industry is not a fad, nor is it a minor blip on the marketing radar. Web services are a big deal, as big as Java in 1995 and XML in 1998. The folks at Sun Microsystems have moved fairly quickly to support important standards like SOAP and WSDL, and to make Web services support a critical feature of EJB and the J2EE platform as a whole. JAX-RPC is a big part of Sun's strategy for embracing Web services. It's a best-of-breed technology, combining the familiar RPC programming model with the newest protocols, to create technology that is both productive and cutting-edge.


What's in Store Next Month

Next month I'll round out this overview of EJB 2.1 support for Web services with a look at SAAJ and JAXM, which are API-based SOAP toolkits, and at the JAXM message-driven bean.



Notes

  1. Tim Ewald, The Web Services Idea, July 12, 2002, Microsoft.com. http://msdn.microsoft.com/webservices/understanding/readme/default.asp

  2. Doug Tidwell, Web services -- the Web's next revolution, November 29, 2000, IBM.com, http://www-105.ibm.com/developerworks/education.nsf/webservices-onlinecourse-bytitle/BA84142372686CFB862569A400601C18?OpenDocument

  3. Paul Kulchenko, SoapWare.org http://www.soapware.org/directory/4/implementations

  4. In the absence of generally accepted terms, the terms API-based and stub-based toolkits have been invented for this article and other works by the author.

  5. Erich Gamma, et. l. Design Patterns, Elements of Reusable Object-Oriented Software, Addison-Wesley (1995), page 87.



copyright notice (c) Copyright 2002 Richard Monson-Haefel. All rights reserved.