ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

JSR 109: Web Services Inside of J2EE Apps
Pages: 1, 2

Implementing Web Services With Stateless Session Beans

One of the coolest parts of JSR 109 is that stateless session beans can be used to quickly and easily develop Web services. A complete review of the EJB specification as it applies to stateless session beans is appropriate for those readers with insufficient EJB background. The important aspects of the specification as it applies to Web services are provided here.



  • Compliance with JAX-RPC rules: Web services must follow JAX-RPC rules in order to correctly interact with clients. See the JAX-RPC page for more information on JAX-RPC.
  • Stateless and transactionless : Web services implemented as stateless session EJBs cannot track any state; nor can they require a transactional context.
  • Compliance with the SDI for the service: In order to operate properly, an implementation must implement all of the methods defined by the SDI for that service.
  • Service interface: Optionally, the implementation may implement the service interface; however, in practice, it's more likely that the implementation will inherit (or have generated for it) the service implementation, much like an EJB does today. Obviously, the bean may also implement other methods besides those defined by the SDI.
  • Comply with the stateless session EJB requirements: Since stateless session Web services are based on the traditional EJB specification, such a Web service must comply with the rules for stateless session beans.

All of the aspects defined above apply to new Web services. What about exposing an existing EJB as a Web service? As long as the EJB follows the rules defined by the specification and doesn't violate the JAX-RPC specification, it may be deployed as an implementation of an existing service. In fact, from the perspective of the EJB container, there is no real difference between the two.

Stateless session beans execute within the context of an EJB container. The container itself controls the lifecycle of a bean, including creating and destroying bean instances. Figure 1 shows the lifecycle of a stateless session EJB. Note that most application servers support a concept of "pooling" or "pre-creating" instances of objects to improve application performance. I've added an additional "conceptual" state representing "pooled."


Figure 1. Stateless Session EJB Lifecycle

  • Does Not Exist: In this state, no instance of the bean is available for use. Beans move from this state to the pooled state or directly to the ready state either because the application server needs a new instance to satisfy a client request or because a number of "pre-created" beans have been specified to exist in the pool.
  • Pooled Unallocated: Not all application servers support the concept of a readily-available pool, and as such, most specifications don't describe the optional "Pooled Unallocated" state. Application servers such as BEA's WebLogic support this intermediate state, where the application server pre-creates a number of instances of the bean, based on a deployment descriptor, that are instantly ready for use. When an application releases an instance of a bean, it can be re-initialized and returned to the pool for reuse.
  • Ready: Beans in the ready state have been created, initialized and are method-ready. Beans in the ready state can accept and process method calls.

Beans move between states for a variety of reasons. Understanding why a bean transitions from state to state will help us understand how to develop beans that behave properly.

  1. Transition 1 represents the initial creation of a bean. Normally, the application server will pre-create some number of beans; however, if the pool is completely in use, and there is available memory, a new instance of a bean would normally be created at client-access time. New beans have their init() method called before they can be used, as any one-time initialization can be done at this point.
  2. Transition 2 repesents the transition from a pooled state to a method-ready state. This transition occurs when a pooled instance is allocated to a client, normally during a get<...>Port() call. Again, the reason for the pooled state is to improve startup performance.
  3. Transition 3 is simply "business as usual." An instance of an object is allocated to a client and the client makes one or more method calls.
  4. Transition 4 occurs when an object is specifically released (i.e., by setting the variable to null) or by going out of scope. Depending on the application server, the bean will transition to pooled and be re-initialized, or go directly to the does-not-exist state.
  5. Transition 5 occurs when the bean is actually de-allocated. The destroy() method is called, and the client can then undo anything done during the init() method.

A note on transactions: The Web services of today are not transaction-aware, and any transaction context is suspended before a bean method is evoked. Practically speaking, this means that beans must not specify or require a transaction context, and as such, cannot be marked transaction "Mandatory."

Implementing Web Services With Servlets

There isn't really a significant difference, conceptually, between implementing Web services using EJBs and implementing with servlets. Choosing servlets as the implementation vehicle is really a matter of personal preference. Web services implemented as servlets need to follow the same guidelines as EJB-based implementations. The real difference between the two is the behavior of the underlying implementation. Table 1 shows some of the most obvious differences. It should be noted that these differences are the opinion of the author and not stated in JSR 109.

Table 1: Differences between EJB and servlet implementations

  Servlet EJB
Lifetime Long-lived Normally short-lived, might be
longer with pooling
Startup overhead Can be significant Normally light
Memory footprint Large Small
Container Services support Some Significant
Lifecycle-aware Marginally Very
Transaction Unsupported Must not be required
Must implement javax.servlet.SingleThreadModel javax.ejb.SessionBean
Scales Poorly Well
When you might choose When a small number of long-lived
methods are required. Startup
overhead not an issue.
When a large number of very
short-lived calls are required.

The one area where Servlet and EJB behavior differs significantly is in lifecycle management. As we saw in Figure 1, an EJB is made aware that is has been created via the init() call, and removed via the destroy() call. The servlet specification has no analogous interface; to support similar behavior, JSR 109 defines an additional interface -- java.xml.rpc.server.ServiceLifeCycle -- that provides similar behavior.

Example 3. java.xml.rpc.server.ServiceLifeCycle

package java.xml.rpc.server;
   public interface ServiceLifeCycle {
   void init(Object context) throws ServletException;
   void destroy();
   } 

Deployment

Deployment solves the problem of isolating the aspects of the Web service specific to how it is used from the aspects specific to its implementation. It normally defines both packaging and naming/initialization. The name of the service and what initialization it might require are examples of deployment-specific concerns that the developer might define as required, but the deployer needs to specify in order for the Web service to operate correctly. JSP 109 piggy-backs its deployment onto the deployment of the normal EJB or Web application via a new deployment description, webservices.xml..

As with so much of JSR 109, deployment of a Web service looks very much like an EJB deployment descriptor. Example 4 shows a sample of how a webservices.xml file might look, and contains five main elements.

  • Port Name: A unique port name that is used by the application server to identify the port. Note that the port name is treated like the EJB name in an EJB deployment descriptor. It is not the actual name of the port, but is used for identification. Declared using the port-component-name element.
  • Port QName: The namespace and WSDL name of the Web service. Specificied using the port-qname-localname and port-qname-namespace elements.
  • WSDL Definition: The path to the WSDL within the packaged .war or .jar file.
  • Service Definition Interface class: The name of the class that implements the service interface functionality of the Web service. Declared using the service-def-interface element. Given that there are two possible implementation mechanisms, it's likely that in practice, this class will be generated, like many of the EJB interface classes.
  • Port Service Implementation: The implementation of the bean is specified with either an EJB-link or servlet-link element pointing to the actual implementation of the service. Since the webservice.xml file itself must be packed within the .jar or .war file containing the implementation of the service, either of these links must have been previously specified. That is, you must reference an existing EJB or servlet.

Example 4 shows how a webservices.xml file might look. It should be noted, however, that this sample was based on the .03 version of the specification, and is subject to change. The code is simple enough (a complete DTD can be found in the specification), but bears some explanation.

Lines 12-16 link the Web service description provided by the WSDL on line 05 to the implementation. Either an EJB or a servlet can be specified as the engine for the Web service, and must be linked back to EJBs or servlets previously defined. Line 11 defines the service interface for obtaining the port for the Web service. Lines 08 and 09 qualify the external name of the Web service, so that any external client might use it.

Example 4. Sample webservices.xml

00 <?xml version="1.0"?>
01 <webservices>
02    <description>My first Web Service using JSP 109</description>
03    <display-name>Sample</display-name>
04    <web-services-description>
05        <wsdl-name>path.to.the.wsdl.representing.the.service</wsdl-name>
06        <port-components>
07           .. various optional elements such as description etc
08           <port-component-name>MyWebService</port-component-name>
09           <port-qname-namespace>qualifying.namespace</port-qname-namespace>
10           <port-qname-localname>name.within.namespace</port-qname-localname>
11           <service-def-interface>com.webservicesareus.webservice.sampleservInt
                      </service-def-interface>
12           <service-impl-bean>
13               <ejb-link>link to a named ejb</ejb-link>
14               or
15               <servlet-link>link to a named servlet</servlet-link>
16           </service-impl-bean>
17        </port-components>
18    </web-services-description>    
19 </webservices>  

JSR 109 is an interesting specification that attempts to define how Web services can be incorporated into an J2EE application server. While there there are some clear questions, such as why MBeans were omitted, the specification does cover the major areas required to define how Web services might be piggy-backed onto existing J2EE applications and within application servers. I'll be watching this JSR closely, along with many of the similar JSPs on security.

Al Saganich is BEA Systems' senior developer and engineer for enterprise Java technologies, focused on Java integration and application with XML and Web services.


Return to ONJava.com.