By now, every Java developer and architect has heard the words "Web service." Loosely, a Web service can be described as any business enterprise asset enabled for access over the Web.
There's a need to make applications accessible independently of the technologies used in the enterprise. The goal is to gain interoperability among distributed systems spanning diverse hardware and software platforms.
SOAP and WSDL are XML-based standards that have made it possible to achieve this goal. SOAP facilitates development of heterogeneous distributed applications by providing a standardized format for transmitting information. WSDL enables Web services to describe themselves to prospective clients. Ubiquitous transport protocols such as HTTP, SOAP, and WSDL free developers from technology and vendor-imposed shackles that have been longstanding consequences of traditional service-based architectures using RMI, DCOM, and CORBA.
The interoperability afforded by Web services forms the cornerstone of any argument that suggests making them a part of B2B and EAI endeavors in enterprise collaboration. In the Java world, enterprise applications are primarily built on the J2EE platform. This article addresses Web service development and deployment in a J2EE environment, discussing various issues that arise in the process.
Web Services vs J2EE
Web services are commonly perceived as a way to interface with back-end systems such as ERP, CRM, order-processing systems, and so on. Even so, they have great untapped potential for opening access to virtually any enterprise application for customers and partners alike.
J2EE provides a hardware-independent platform for building these distributed enterprise applications. It provides many benefits, such as a component-based development model; scalability; object life cycle management; transactional access to existing systems using JDBC, JTA, and JMS; and a unified security model. However, the J2EE specification by itself doesn't perpetuate the more open software-independent advantages of Web services. Nevertheless, it doesn't preclude the inclusion of SOAP or WSDL and the deployment of Web services in a J2EE-driven enterprise (there is currently a proposed final v0.8 of the draft JAX-RPC specification defining a standard Java API for developing and accessing Web services. Indeed, the J2EE platform is an excellent vehicle to provide the necessary plumbing for the development and deployment of Web services. Premier application server vendors such as BEA and IBM have already delivered J2EE-based Web service solutions with their recent versions of WebLogic and WebSphere products respectively. As such, services deployed using these products inherit all the benefits of J2EE, while at the same time providing their clients with increased technology independence and Internet accessibility.
A Web Services Opportunity
Consider the scenario in which broker ZTrade.com provides the best commissions for online trading and portal EveningSat ellite.com lets registered users track portfolios online. ZTrade is a bare-bones operation. Its Web site doesn't provide any sophisticated stock screening or asset-management tools. As an added benefit to its clients, ZTrade decides to forge an alliance with EveningSatellite so it can create and maintain portfolios at the portal's site. ZTrade users can simply log on to Evening Satellite and perform various research tasks on their portfolios. Ztrade's basic requirement: the ability to update client portfolios at EveningSatellite in real time as trades are executed.
EveningSatellite needs to make its portfolio-tracking application accessible to enterprise applications of partners such as ZTrade. Together, both parties can develop an efficient proprietary solution. However, in the future, when EveningSatellite wants to offer similar services to other partners, the wheel will need to be reinvented, given the diverse technologies used by prospective partners. Deploying a portfolio-management Web service is the ideal solution for Evening Satellite.
A simplified view of the J2EE-driven Evening Satellite Web site is shown in Figure 1, with the requirement of a Web service included. The interface from the Web tier to the EJB tier is primarily through two stateless session beans specified by UserManager (see Listing 1)and PortfolioManager (see Listing 2). As the names suggest, UserManagerSession handles client user registration, authentication, and related tasks, while Portfolio ManagerSession provides portfolio creation and maintenance functionality. The former makes use of the latter when required, for example, to purge the portfolio of a user that is unregistered. Obvious methods provided by these interfaces, such as getPortfolio-Details() in PortfolioManager and change-Password() in UserManager, have been excluded for clarity.
Enterprise JavaBeans as Web Services
Let's assume WebLogic 6.1 is being used as the application server and Web services platform. Any stateless session bean in Web Logic can be easily exposed as an RPC-style service (support for message-style services is also available but is outside the scope of this article). The interface for the EJB doubles as the interface for the service. PartnerService (see Listing 3) and PartnerServiceSession (see Listing 4) provide the interface and implementation for our service.
It would have been just as easy to expose both UserManagerSession and Portfolio ManagerSession as two individual services. Such session beans are viewed as facades into an enterprise application. The interfaces from such facades do not necessarily translate to interfaces required of Web services. Partner- Service provides a much-needed abstraction that exposes only those aspects of the EveningSatellite back-end systems of interest to the partners. ZTrade can verify a user exists when a client provides a userId, or create a user at EveningSatellite and provide the password to the client. Methods such as change Pass-word() in UserManager are absent from the service interface for good reason.
For the sake of simplicity, PartnerService method signatures only use primitive data types. Due to differences in the level of support for user-defined types across various implementations today, it may be best to rely on simple data structures and primitive data types. In B2B and EAI scenarios, XML is the format of choice for communicating information. This XML can be passed as a string, rather than say, XML-node data structures, to ensure all implementations can handle it.
The practice of making method signatures independent of artifacts used in the underlying application can go a long way toward decoupling systems and increasing technology options. The SecurityInfo JavaBean supplied to PortfolioManager. updateSecurity() was perceived as an internal implementation detail and thus not exposed in the Web service interface.
Implementations typically provide facilities for generating the WSDL for a service and generating classes or data structures for types described in a given WSDL (WebLogic takes a slightly different tack for providing the latter functionality; it packages its client-side API with any other service-dependent classes in a JAR that can be downloaded).
Let's examine the implementation of the Create User use case for our service (see Listing 4). It looks up the home interface for UserManager, creates an instance of the session bean, and simply invokes the appropriate method on it. An application exception User ManagerException, thrown from UserManager, is treated as a system exception (for illustrative purposes only) and rethrown as an EJBException. WebLogic translates the resulting RemoteException thrown by the EJB container into a SOAP fault in the outgoing SOAP message.
Web Service Deployment
It should be no surprise that Web services are deployed using a servlet in a Web application provided by a given implementation. WebLogic uses the Web logic.soap.-server.ser vlet.Stateless Bean Adapter servlet. As the name suggests, it adapts incoming SOAP message invocations to methods on stateless session beans. WebLogic ships with an Ant
(http://jakarta.apache.org/ant/) task "wsg en" that facilitates deployment of a Web service as an application archive (EAR) containing the servlet in a Web archive (WAR) and the stateless session bean for the service in an EJB archive (JAR). The items of most interest in the Ant build script (see Listing 5) are the name of the service bean, ejb/Partner Service, the context partners that form part of the WSDL URL, and the EJB archive name, portfolio service.jar, containing the service bean. For detailed information on developing Web services with WebLogic, refer to http://e-docs.bea.com/wls/docs61/webServices/index.html.
Web Service Invocation
CreateUser (see Listing 6) shows how a service operation is invoked using the WebLogic client API. As mentioned earlier, clients can download a JAR from a Web page available for the Web service on deployment. The WSDL URL used follows this pattern:
http://[host]:[port]/[context]/[JNDI-Name]/[JNDI-Name].wsdl
Note that the JNDI name for the service bean is specified in the WebLogic EJB deployment descriptor weblogic-ejb-jar.xml (see Listing 7) for portfolioservice.jar.
Exception Handling
When using the WebLogic client API, any exception generated by the service manifests itself as a weblogic.soap.Soap Fault exception at the client. If a user, "tom", exists in the system, then CreateUser dumps the following, including the SOAP fault to stdout.
User tom NOT created!
Fault Code: Client
Fault String: java.rmi.RemoteException
Fault Detail: Application fault:
java.rmi.RemoteException: EJB Exception: ;
nested exception is:javax.ejb.EJBException
- with nested exception:
[com.axyssolutions.ejb.UserManagerException:
User tom already exists!]
(deeper stack trace omitted)
WebLogic uses the class name of the exception thrown by the EJB container, in this case java.rmi.RemoteException, as the fault string and throws in the stack trace as the fault detail for good measure. Ordinarily, it should be possible for a service to specify information for these fault attributes. This is explored in more detail later.
To EJB or Not to EJB
Most J2EE-based implementations use servlets to map incoming SOAP messages to invocations on a Web service. In this context, a "Web service" is the physical manifestation of executing code. In WebLogic, it happens to be a stateless session bean activated in its EJB container. But this isn't always the case in other implementations. For instance, WebSphere and GLUE (from The Mind Electric) also allow a simple JavaBean or class to act as the Web service as well.
Discovering which operations a stateless session bean exposes is a matter of inspecting its remote interface. When a Java class is used to represent the service, its public methods can be introspected under the assumption that all of them are part of the service interface. Either way, these methods, with their signatures, can be specified as operations in the corresponding WSDL. One advantage of using a Java class is that only one instance must be created when the service is stateless.
The WebLogic implementation leverages its EJB container to deliver Web services as stateless session beans. This is a very reasonable approach that yields standard J2EE deployment and configuration semantics with its deployment descriptor and JNDI naming context. It also imparts an important benefit to Web services declarative transaction management. Transaction behavior of an EJB can be controlled using its deployment descriptor, which sets transaction attributes for individual methods. Thus, the transaction context for a service session bean method can be propagated to one and all beans used within the method. This is especially useful if an application session bean can be used as-is for the service.
Other factors can influence a given Web service implementation. It's reasonable to expect that business partners will want to communicate information using XML. It's equally likely that some legacy client application generates data feeds consisting of name-value pairs. Given that an application is already deployed for traditional Web-based access, developing a session bean for the sole purpose of parsing input to feed application beans may be overkill. You wouldn't normally want to deploy parsing logic in the EJB Tier, which should ideally focus simply on the business aspects.
In the above situation, a Java class deployed for access through a Web application may be a better alternative. The service could then be pushed out to the Web tier. This could lead to more efficient use of resources especially when multiple stateless services are needed as it translates to reduced object creation. All invocations on the service can be mapped to a single class instance rather than a session bean selected from a pool. Besides, a Java class is a more manageable undertaking than a session bean with its remote and home interfaces, and implementation class. Using a Java class can lead to a reduced number of deployment issues.
Another situation worth exploring is when the functionality to be exposed doesn't use any session beans. Consider a set of use cases, each requiring access to only one entity bean. The application may then dispense with the additional level of indirection available through a session bean. Given that a session bean is not readily available, you now have to decide whether to go with a stateless session bean or a plain Java class. Sometimes, it's more natural to view a Web service as a Web application component that's a client of beans in the EJB tier, rather than part of it.
Using a Java class for the service is not without its drawbacks. We lose declarative transaction control for the service methods, which may or may not be an issue. It depends on how many beans are explicitly accessed by a service method. If the point of access into the application for a given method is through one bean only, then its descriptor can be used for managing the transaction. If multiple beans need to be accessed, it's the Web service's responsibility to explicitly demarcate transactions (see Listing 8). Other J2EE benefits unavailable when using a Java class include explicit role-based access control, deployment, and configuration facilities.
A Java class may be a better option for a read-only service that generally doesn't need transactional control. A StockQuote service doesn't have to be transactional, unlike a StockTrader service, for which a stateless session bean may be more appropriate.
Matters of State
As we saw earlier, it's possible to deploy stateless session beans as Web services. One question that begs asking is: Why use a stateless rather than a stateful session bean?
A Web service provides an interface with a unified set of operations exposing some functionality. Unlike HTTP, SOAP doesn't provide any artifacts that help in managing session state across multiple invocations. SOAP headers can conceivably be used to implement a stateful model for a service. One may implement a custom solution by passing a session-id in the SOAP headers. Unless such headers are standardized in the SOAP specification, solutions using them won't be vendor-neutral.
State management is a feature that maps naturally to technologies used in the Web tier. It can be implemented quite efficiently with HTTP session management support provided by the servlet API, with the service itself remaining stateless. Though most implementations use HTTP to send and receive SOAP messages, other protocols, such as SMTP, may also be employed. If the service is to behave independently of the transport protocol used to access it, then stateful solutions are best implemented within the Web service infrastructure. This may involve using an application server's proprietary features in the absence of standards for state management in Web services.
Regardless of which protocol is used, it's possible to implement Web services to expose the standard J2EE state-management modes of "application", "session", and "request". Web Logic doesn't provide any functionality for implementing stateful Web services. Examples of platforms that do so (to varying degrees) are WASP, from Systinet, and GLUE.
When the application mode is used, all invocations are mapped to a shared implementation instance for the service. In this case, the implementation can simply map to a singleton instance of a Java class or to a stateless session bean. In the latter case, any application state would have to be persisted in in-memory caches or a database. When the request mode is used, an invocation readily maps to a stateless session bean or to a Java class instance. A new (or pooled) instance is used to handle each invocation. When the session mode is used, an invocation maps to either an HTTP session that passes required state information to a stateless session bean or Java class instance, or to a stateful session bean. The latter alternative is obviously the logical choice when a protocol other than HTTP is used.
Developers can reasonably expect support for state management modes to be a feature provided by a given implementation and typically shouldn't have to implement it.
Customizing Web Service Errors
At the time of writing, the WebLogic implementation lacks support for enabling a Web service to include application-centric errors in the SOAP fault, and more importantly, the fault detail. The implementation simply uses the exception stack trace for the fault detail. When specific error information needs to be communicated to clients, other implementations such as Apache SOAP or GLUE can be plugged into WebLogic (or any other J2EE-compliant server of choice).
Let's examine how to implement an Asset Service Java class for our service using GLUE 1.x. The AssetService methods are essentially similar to those of Partner ServiceSession, but with one notable difference. They all throw an electric.net. soap.SOAPException. GLUE takes any exception thrown from a service and makes it available at the client as an instance of SOAP Exception. To explicitly communicate a fault to a client, the service can throw an instance of SOAPException that GLUE simply echoes at the client.
The AssetService.createUser() implementation (see Listing 9) assumes that when an application exception is thrown from the UserManagerSession, it is because the specified user already exists. It then suggests alternative userIds to the client using the fault detail. Thus, the CreateUser version for GLUE (see Listing 10) dumps the following SOAP fault to stdout if user tom already exists in the system.
User tom NOT created!
Fault Code: Client
Fault String: User tom already exists!
Fault Detail: <detail>
<userId>tom101</userId>
<userId>tom102</userId>
<userId>tom103</userId>
</detail>
GLUE can deploy Web services using its own Web server or in any J2EE-compliant application server. The source code accompanying this article was deployed using GLUE in WebLogic. GLUE can wrap incoming invocations to either a Java class or a stateless session bean. A Web application containing the electric.servlet. http.Servlet Server servlet has to be configured with the appropriate properties. For detailed information on implementing Web services with GLUE, see
www.themindelectric.com/products/glue/glue.html.
Securing Web Services Confidentiality
SSL over HTTP can be used for encrypting invocations on Web services. The standard JSSE (Java Secure Socket Extension) libraries can be readily used. In GLUE, for example, the standard javax. net.ssl.trustStore and javax.net. ssl.trustStorePass word properties must be set to the location and password of the certificate file. To bind to a service deployed securely, the WSDL URL specified by the client should begin "https:" instead of "http:". Appropriate with steps must be taken to deploy the underlying service applications securely at the back end.
Authentication
HTTP-based authentication is a popular method for restricting access to resources on a Web server. The SOAP client sends the username and password as a base 64-encoded string in the appropriate HTTP header. Certificate-based authentication may also be used if required. However, HTTP authentication is the least common denominator supported on all server platforms and is easily implemented over SSL. Custom authentication is possible using SOAP headers that can be verified by the Web service implementation.
Authorization
Authorization can be implemented in the same way as for any J2EE application. Once a client has been authenticated using HTTP-based authentication, authorization can be performed in the standard J2EE realm/role-based manner.
Conclusion
Web services are moving the Internet toward a service-oriented architecture in which client applications and Web services can use other Web services on demand. With the vast number of J2EE applications already deployed, it makes sense to expose their interfaces as Web services. This is especially important, not to mention convenient, since it can all be done while retaining the benefits of J2EE.
Various J2EE application server vendors are already shipping Web services-enabled products. SOAP and WSDL support can vary greatly from one product to another. As we've seen, however, the J2EE architecture makes it possible to plug in custom and off-the-shelf components to yield optimally configured solutions. Web services not only coexist with applications executing within J2EE containers; they open up a whole new client space for these applications.
Acknowledgement
I would like to thank Rhett Guthrie at Axys Solutions for his guidance.
Author Bio
Saurabh Dixit is a senior technology partner at Axys Solutions, a professional services consulting firm based in Dallas, specializing in IS architecture, Java enterprise development and Web services.
sdixit@axyssolutions.com
All Rights Reserved
Copyright © 2004 SYS-CON Media, Inc.
E-mail:
info@sys-con.com