Chapter 15. Exposing EJBs as web services – EJB 3 in Action

Chapter 15. Exposing EJBs as web services

This chapter covers

  • Web service primer
  • Java-XML web services
  • Developing EJB web services

Service-oriented architecture (SOA) and web services are no longer buzzwords. These technologies have become a reality in the past few years. Web services are definitely the new industry standard for application-to-application (A2A) and business-to-business (B2B) integration.

What do web services have to do with EJB 3? Exposing your business logic component as web service is a snap with EJB 3. Stick with us through this chapter and we’ll demonstrate how EJB 3 can be combined with web service metadata to provide compelling solutions for exposing business logic as web services.

Let’s illustrate this with another scenario from the ActionBazaar application. The promoters of ActionBazaar are being forced to expose some components as web services because their competitors now offer competing services. ActionBazaar wants to stay competitive, and needs to quickly enable their business functionality in a way that users of the system can easily consume.

At first, they thought they might have to move to the Microsoft .NET platform to create the web services. When you consider that J2EE 1.4 was criticized by many for its complexities in building service-oriented applications, it’s easy to see why the caretakers of ActionBazaar were considering that move. They heard rumors that the developers of KabadiBazaar,[1] a sister web auction site similar to ActionBazaar that specializes in miscellaneous household items, had demonstrated how it was easy to build web services with .NET. The promoters of ActionBazaar are hesitant, though, because they are enthusiastic about the simplification of web service development brought to Java by using metadata annotations and the Java API for XML-Based Web Services (JAX-WS) 2.0 specification. In the end, they have decided to create their web services using EJB.

1 In Hindi, KabadiBazaar is a marketplace where household junk/scraps are sold.

This chapter assumes that you are familiar with web services, and in-depth coverage of web service development with the Java EE platform is not within the scope of this book. Other books are available on that topic; it would be difficult to cover all aspects of web service development in a single chapter.

In this chapter we first offer a quick review of a web service and its components, and discuss high-level approaches to web service development. We follow this with the details of building EJB web services, and conclude with some best practices to get your web services up and working quickly with EJB 3.

15.1. What is a web service?

It’s very difficult to arrive at a single definition of web service that all camps will agree on. Simply put, a web service is a standard platform that provides interoperability between networked applications out of the box. For example, if you build a web service using Java EE and deploy it to an application server, you can invoke that service from any of a number of possible client applications interested in the service. This even includes client applications built using the Windows Communication Foundation[2] (WCF, formerly code-named Indigo), Microsoft’s latest web service platform.

2http://msdn.microsoft.com/winfx/technologies/communication/default.aspx

SOA is a new way of building loosely coupled applications. With SOA, you focus on building services. Thus, services are somewhat analogous to Java objects and components such as EJBs. Unlike objects, however, services are self-contained, maintain their own state, and provide a loosely coupled interface. Simply put, a service is a self-contained software module that performs a predetermined task: validating a credit card, for example. Many developers think SOA and web services are the same, but in reality SOA is an architecture principle whereas a web service is a platform to build loosely coupled applications. You can implement a service-oriented application with many other technologies such RMI but web services has been the most popular technology to implement service-oriented applications.

The most important aspect of a service is the service description. When using web services as the implementation technology for SOA, Web Services Description Language (WSDL) describes the messages, types, and operations of the web service, and is the contract to which the web service guarantees it will conform.

Let’s start with an example. Assume that ActionBazaar built a web service and provides a WSDL that describes the service. The service is registered in the UDDI (Universal Description, Discovery, and Integration) registry. A client application (KabadiBazaar) finds the WSDL describing how to call the service from the registry, generates the endpoint interface and proxy classes, and then invokes the web service as shown in figure 15.1.

Figure 15.1. ActionBazaar built a web service and registered it in the UDDI registry. A client application searches the registry to find the service. The registry returns the WSDL registered by the service, and uses the WSDL to invoke the web service.

Beside interoperability and application integration, the primary benefit that a web service provides is reusability of discrete business functionality. How this functionality might be used is rarely known in its entirety when the service is created (sometimes known as publishing the web service). Client applications can even search for multiple similar services and determine which one to use on the fly at runtime, depending on known data, user preferences, user locale, or any number of other circumstances unique to the client application at that moment in time. The ActionBazaar developers build a few loosely coupled services such as Credit-VerificationService and CreditCardChargeService. These are exposed as web services and are seamlessly found and consumed by the KabadiBazaar application, even though it was built using a completely different technology. Of course, 100 percent compatibility between different platforms is still eluding the masses. Most developers are more than willing to accept 95 to 98 percent compatibility out of the box and make the final adjustments themselves. The alternative is to do a lot more work, for a lot less reward.


Web Services-Interoperability (WS-I)

WS-I (www.ws-i.org) is an open industry consortium, with members from diverse industries. It consists of large vendors such as Microsoft, Oracle, IBM, BEA, and Sun Microsystems. WS-I’s primary goal is to promote interoperability of web services across middleware platforms, operating systems, and programming languages.

WS-I provides a specification known as Basic Profile that lists a set of recommendations to achieve maximum interoperability of web services between heterogeneous platforms. Java EE 5 requires support for the Basic Profile 1.1 specification in order for any implementation to claim compatibility.


We recommend you check out Eric Pulier and Hugh Taylor’s Understanding Enterprise SOA (Manning, 2005) for more in-depth coverage of this topic. Also, here are some web sites to visit:

In this section we’ll first look at core components of a web service. Then we’ll discuss the various styles of web services and their differences. Finally, we’ll examine some approaches to web service development.

15.1.1. Identifying web service components

The web service landscape is comprised of an alphabet soup of standards, protocols, and technologies. At its core, a web service is published by a service producer and accessed by a service consumer. This almost always ends up with an XML document being sent over an HTTP transport. As a general rule the data protocol shared between service consumer and producer is based on some flavor of XML, but the transport can be any network protocol. Implementations exist for several standard transport protocols besides HTTP, including JMS, SMTP, and FTP.


REST web services

Representational State Transfer (popularly known as REST) is a popular architectural style of building web services. It doesn’t depend on a SOAP envelope, but it does leverage XML and the HTTP protocol. Statistics revealed by large web-based companies like Amazon and Yahoo! shows that a majority of their consumers use a REST interface.

Unfortunately, Java EE 5 doesn’t require support for REST web services and each vendor supports its own approach. GlassFish supports RESTful web services by creating an implementation of the javax.ws.Provider interface. Vendors such as Oracle allow you to convert a Java object into a web service by using proprietary configuration or a proprietary annotation. Check your vendor’s documentation to see if they provide REST support, and see how that support is implemented. For more information on REST, hop over to http://en.wikipedia.org/wiki/Representational_State_Transfer.


Several approaches are available for implementing a web service. The three most widely used are REST (Representational State Transfer), XML-RPC (Extensible Markup Language–Remote Procedure Call), and SOAP. Although there are valid reasons to use REST and XML-RPC, the majority of enterprise applications use some form of a SOAP stack for their web services. This is primarily due to the fact that most standards for sharing industry-specific data (such as travel, health care, financial) via web services are based on the SOAP architectures. This chapter will focus on the SOAP stack because it is the most prominent of the three architectures.

That’s enough talk about the general SOA landscape. We’ll start with some basics of the SOAP architecture. Let’s begin by defining what a typical SOAP stack includes:

  • Service messaging— Messages are sent between the client and service in XML, the universal format for metadata. For a SOAP stack, this means that the messages follow the SOAP standard for message structure and definition (www.w3.org/TR/soap/).
  • Service description— Each web service has a corresponding XML document that describes the web service, the parameters that it expects to be passed, which ones are optional and which are required, what their data types are, what will be returned, and so forth. A web service client “consumes” the WSDL file in order to communicate with a web service (www.w3.org/TR/wsdl).
  • Service discovery— Think of this as the Yellow Pages for web services. When a web service wants to make itself known, it registers itself to a UDDI registry by providing the WSDL required to access the service. Clients can browse registries looking for services that meet their requirements (www.uddi.org/specification.html).
  • Service transport— This is the network mechanism responsible for transporting messages between the client and the service. The Hypertext Transfer Protocol (HTTP) is most commonly used, but any transport should work.

Stick with us as we take a closer look at these web service building blocks.

Defining a message: SOAP

The Simple Object Access Protocol (SOAP) is a distributed protocol similar to CORBA and Java RMI. It lets applications talk to each other by exchanging messages over a network protocol, most commonly HTTP. SOAP is heavily dependent on XML, and every SOAP message is an XML document that contains several elements (such as Envelope, Header, and Body). The SOAP header contains application-specific infrastructure data, such as security information. The SOAP body contains the message being exchanged between applications. While the SOAP header is optional for a SOAP message, the SOAP envelope and body are mandatory.

Here is an example of a SOAP message with an empty header. The body includes an XML representation of ActionBazaar’s addBid method with its parameters:

<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<addBid xmlns="http://actionbazaar.com/Bidding">
<user-id>viper</user-id>
<item-id>100</user-id>
<bid-price>2000.24</bid-price>
</addBid>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

This snippet shows the skeleton of each and every SOAP message. The message starts off with an Envelope, which typically declares a namespace and may include encoding. Immediately inside the Envelope is the Header, which is optional. This contains meta-information about the message, such as security, network routing, and other data required to get the message to its destination. The last piece of the SOAP message is the Body, which in the case of our example, defines the addBid method and its associated parameters.

Describing a web service: WSDL

The Web Services Description Language (WSDL) is central to a web service because it describes the service to possible consumers. It specifies the message type, port, supported operations, data types, and all other details about how the web service works, where it can be found, and what the client should expect in return. Listing 15.1 shows a sample WSDL for ActionBazaar’s PlaceBidService.

Listing 15.1. WSDL for the PlaceBid service

Let’s briefly look at some important parts of a WSDL. In listing 15.1, the types element defines the data types exchanged when the web service is invoked. The parameters passed to and returned from a method are considered data types. The code defines the messages the service supports. A message may contain more than a message part. Each message part is actually part of the SOAP message being sent, and is either a parameter or result being passed. The code then defines the portType. A portType is the most important part of a WSDL; it defines operations that can be performed and the messages involved. The message, operations , and protocol details of a service are defined using a binding . This example defines the service to be a document style service. Finally, the code defines a top-level service that uses the binding we defined, using the port definition .

Java to WSDL mapping

There is no one-to-one mapping between XML data types and Java; there never has been. This presents a problem because the data types expected by a service are defined in the WSDL. If a service is implemented in a non-Java language, that language must provide support for binding XML to it. But when a service is implemented in Java, the binding is accomplished through the Java Architecture for XML Binding (JAXB) 2.0 specification. JAXB allows web services to use the complete XML schema, which results in improved interoperability and ease of use.

While the details of binding Java to WSDL are beyond the scope of this book, you can find out more from the Java API for XML-Based Web Services (JAX-WS) specification at http://jcp.org/en/jsr/detail?id=224, and check out the JAXB specification at http://www.jcp.org/en/jsr/detail?id=222. You’ll find an easy-to-use reference for mapping Java data types to XML and WSDL types at http://download-west.oracle.com/docs/cd/B25221_04/web.1013/b25603/apptypemapping.htm#BABCCAHA.


XML-RPC

When the forerunner of web services was in the lab of UserLand, Microsoft thought it might be something of value. Distributed remote procedure calls could be one way to solve certain technical problems they were looking at, and XML was just coming on the scene and gaining a lot of industry acceptance as a general-purpose metadata language. The team dubbed this new beast XML-RPC and the specification was less than seven pages long!

All of this was going along swimmingly until Microsoft decided they would rather go a different direction. Microsoft leaving the party wasn’t a problem until about a year or so later, when they wanted back in. Their return to the idea of web services was different this time and they wanted more control of the XML-RPC direction. Users of XML-RPC were now concerned about the future of their successful little protocol, and what would happen if Microsoft took the reigns. UserLand and others in the community opted to make XML-RPC open source to avoid a Microsoft power play, and of course the Redmond Giant opposed this move. After wrestling for months, Microsoft eventually decided to go in a different direction, and began promoting what we now know as SOAP. As Paul Harvey is fond of saying, here’s the rest of the story...

According to rumors, the original web service protocol was named SOAP. As you know, SOAP stands for Simple Object Access Protocol. A specification that can be defined in only seven pages definitely meets the “Simple” criterion. But when Microsoft wanted to part ways the second time, they wanted to take their name with them. The community of SOAP users at that time renamed their protocol XML-RPC, and Microsoft dubbed their new web service protocol SOAP. This explains how the SOAP protocol, which is neither simple, nor an object access protocol, got its name. At least that’s how the rumor goes!

You can find out more about XML-RPC at http://en.wikipedia.org/wiki/XML-RPC.


Discovering a service: UDDI

If you plan on having a lot of services to share, you’re going to need a way to find them. That’s the whole reason that UDDI was invented. UDDI is a platform-independent, XML-based registry that enables clients to find available services.

The basic process is that a service can publish information about itself to a known UDDI registry, including the WSDL required for a client to communicate with the service. A client can search the registry looking for a particular type of service, vendor name, and similar information. Once a service catches the eye of the client, the client requests the WSDL for the service. The client will then consume the WSDL, bind to the service, and invoke the service using the published service description.

It is possible for mere humans to browse UDDI registries and manually sift through available services. This might be something interesting for you to do if you have never experienced a UDDI registry, or you aren’t familiar with how they work. You can check out one such UDDI browser at http://soapclient.com/uddisearch.html and take a peek at the services hosted at this site while you’re there.

For more details about the UDDI specification, hop over to www.oasis-open.org/committees/uddi-spec/doc/tcspecs.htm. Just be careful when you get there and make sure you can find your way out; we wouldn’t want to lose you in the registry...

Transporting messages

For a service consumer and producer to communicate, they need a way to send messages to each other. These messages are sent over a network using a protocol that both parties can support. Given that the Web is ubiquitous, HTTP is everywhere. It makes sense that it would be the most widely used transport for web service messages. HTTP also has the advantage that it is one of the few protocols allowed through firewalls, as long as well-known ports like 80 and 8080 are used.

But as we stated, web services just need to operate over a network. That means almost any network protocol could be used to transport messages. Where HTTP is not an option, some protocols that are in use include SMTP, FTP, and JMS. What? Your favorite gopher protocol not in the list? Why not grab the SOAP spec and implement it yourself? That ought to be a fun weekend project.

15.1.2. Web services styles

There are two primary types of web services styles: RPC-oriented and document-oriented. The RPC style of web services was popular initially, but more recently the pendulum has swung in the direction of document-oriented web services. One reason for this shift is that you can make better use of an XML schema with document-oriented web service. To learn some of the differences between RPC and document-oriented web services, visit http://expertanswercenter.techtarget.com/eac/knowledgebaseAnswer/0,295199,sid63_gci984152,00.html.

The messaging style for a web service may be either literal or encoded. When you use literal, the messages are exchanged with plain XML. However, an encoded message includes an external rule about how to decode the message. The receiver of the message has to decode the message by using the decoding attribute. The WS-I Basic Profile 1.1 doesn’t support encoded messages.

The most popular combination of web service style and messaging style is document/literal. This is because the WSI Basic Profile only supports the document/literal combination for maximum interoperability between platforms. Document/literal-style messages are constrained by an XML schema. The schema can reside in the WSDL or can be referred to with an URI. The end result is that you can manage the structure of your message in the same way that DBAs manage table definitions with versioning. The RPC/encoded combination puts the schema in the actual message itself, which makes it much more tightly coupled to the message. Stick with what the WSI Basic Profile supports (document/literal), and your web services will enjoy maximum interoperability and acceptance by the widest possible audience.

15.1.3. Approaches to developing web services

Only a few standard approaches exist for building a web service. These approaches are independent of whatever tools you may be using but are somewhat specific to the SOAP style of building web services.

Bottom up

The bottom-up strategy is the most popular approach to developing a web service. It allows you to reuse your investments by exposing your existing applications. For example, ActionBazaar is an existing application with proven business value. Competitive pressure is moving ActionBazaar to expose some of this business functionality as web services. The implementation class already exists. All that is needed is to create a WSDL and expose the implementation class as a web service. Java EE 5 allows either POJOs or stateless EJBs to be exposed as web services. Most application servers provide tools and utilities to generate WSDL from existing Java classes.

Top down

Top down is the correct way to build any new web service, and is often termed the “pure approach” to building a web service. Also known as contract first web services, this approach starts with the WSDL (the contract) by defining operations, messages, and so forth. Then you build the endpoint interface, and finally the implementation class. If you are building a web service from scratch, we recommend that you follow this approach. Most application servers provide development tools to create WSDL and then provide the ability to generate a Java class from the WSDL. Just add your business logic to the generated class, stir in a little water, bake at 350 degrees for 5 minutes, and your new web service should be ready to pop out of the oven!

Meet in the middle

In the meet-in-the-middle approach, you start with both the WSDL and implementation class and wire the WSDL with the implementation class. This is harder to implement and can be difficult to maintain since you have to pay a lot more attention to keeping things in synch. We recommend you avoid this approach if at all possible.

The movement from the bottom-up to the top-down approach of building SOAP-based web services is still in progress. Many IT shops are still using bottom up as the tool support is by far the best for this approach, and because web services have been limited to use within the enterprise for many industries. As interoperability between companies and technologies increases in value, we expect top down, specifically contract first web services, to become the widest adopted approach to defining and building web services.

Now that you are aware of the approaches to building SOAP-based web services, what protocols and standards exist to assist you in such an endeavor? The next section points you down the path that so many have helped to build: the path to the Java web services platform.

15.2. JAX-WS: Java EE 5 web services platform

Java EE 5 provides a robust platform on which you can build and deploy web services. Java EE 5 allows you to build web services with either regular Java class (POJO) or EJB 3 stateless session beans. In this section we’ll briefly introduce the web services platform and then explain why you would choose EJB 3 session beans over POJOs.

15.2.1. Introducing the web services platform

The Java API for XML-Based Web Services (JAX-WS[3]) 2.0 is the core specification that defines the web services standard for Java EE 5. JAX-WS 2.0 is an extension of the Java API for XML-RPC (JAX-RPC) 1.0. The goal for JAX-WS 2.0 is to simplify development of web services applications. It depends on several other specifications, listed in table 15.1 You can expect that several books will be written about these specifications, and we encourage you to become familiar with them as they are made available.

3http://www.jcp.org/en/jsr/detail?id=224

Table 15.1. Specifications Java EE 5.0 builds on to support web services

Specification

Purpose

Java API for XML Web Services 2.0

Platform specification

Java API for XML Binding 2.0

Binding for WSDL to Java

WS Basic Profile 1.1

Interoperability with .NET

Web Services Metadata 2.0

Metadata approach to define web service

Java API for XML RPC 1.1

Backward compatibility with J2EE 1.4 web services

As you can see on table 15.1, a lot of time and sweat has been spent by various industry groups in thinking about and defining web services. Folks who tell you web services are still in their infancy are just not up to speed with what’s going on in this arena. This chapter is littered with references pointing you to just a fraction of the overwhelming amount of information available on web services. If you want more in-depth coverage of a specific topic, you’re only a browser page or two away from opening the mother lode!

Of course, this begs the question: why consider using EJB 3 as your web service implementation instead of POJOs? There are some distinct advantages to the EJB 3 option, which we discuss in the next section.

15.2.2. Why choose EJB over a POJO for a web service?

JAX-WS 2.0 allows both regular Java classes and stateless EJBs to be exposed as web services. If you were using J2EE 1.4, you’re probably wondering why you’d use a stateless EJB as a web service. A look at the code for a POJO and for EJB 3 web services reveals that there are hardly any differences, with the exception that the EJB 3 web service will have a few extra annotations. A Java class web service is packaged in a web module, whereas an EJB web service is packaged in an EJB-JAR.

Both a Java web service and an EJB web service support dependency injection and lifecycle methods such as @PostConstruct and @PreDestroy, but you gain a few extra benefits from using EJB 3 web services.

First, you automatically get the benefits of declarative transaction and security available only to EJB 3 components. You can use interceptors and the timer service if your applications need them, without depending on extra layering.

Second, a web service that uses EJB 3 can easily expose your business applications using additional protocols, such as RMI, by adding a remote interface. As you saw in the previous section, exposing an EJB 3 stateless session bean is easy and can be done by simply adding the @WebService annotation.

Table 15.2 compares the features supported by EJB 3 web services with a regular Java web service.

Table 15.2. Feature comparison of Java web services to EJB 3 web services

Feature

Java Web Service

EJB 3 Web Service

POJO

Yes

Yes

Dependency injection of resources, persistence units, etc.

Yes

Yes

Lifecycle methods

Yes

Yes

Declarative transaction

No

Yes

Declarative security

No

Yes

Requires annotation processing in an external Annotation Processing Tool (APT)

Yes

Most EJB containers do not require this.

Can be run in a web container like Tomcat

Yes

No

When this chapter was written, most Java EE containers required regular Java classes using web services metadata to run through an annotation processor before deployment. This is in contrast to EJB 3 annotations, which are dynamically processed during deployment, thus greatly simplifying the development process. This optimization is yet another reason to consider using EJB 3 for your web service implementations.

Next we’ll see how to expose a stateless EJB as a web service, as defined in the Web Services Metadata 2.0 specification. This isn’t the only way to expose an EJB as a web service (you could use deployment descriptors), but you’ll go this route if you’re using the JAX-WS 2.0 approach. If you like annotations, this one’s for you!

15.3. Developing EJB web services with JAX-WS 2.0

Using JAX-RPC web services with EJB 2.1 makes exposing a simple EJB as a web service a lot more difficult than it should be. You have to perform the following steps, typically by hand:

  • Generate the WSDL describing the service.
  • Build a service endpoint interface (SEI)—the actual service portion of the web service.
  • Identify the endpoint interface in ejb-jar.xml.
  • Package all of these with webservices.xml.

If you prefer that approach, you can certainly use it—every time you want to publish a new service! The good news is that EJB 3 and JAX-WS 2.0 tremendously simplify the whole process. You don’t piddle around with WSDL, mapping files, or descriptors, as these are automatically generated for you during deployment. Web service metadata makes bottom-up development much simpler.

Let’s first see a straightforward EJB 3 example exposed as a web service, and then dive into the details of some commonly used annotations that can make defining web services even easier. Listing 15.2 shows the PlaceBid bean exposed as a web service.

Listing 15.2. PlaceBid EJB as a web service

In listing 15.2, we used the @javax.jws.WebService annotation to expose PlaceBidBean as a web service. You can use the annotation with an endpoint interface or the bean class itself. As in our example, if you use the @WebService annotation in the bean class the endpoint interface will be generated automatically. We’ll elaborate on the details of this annotation in the next section. We specified that the web service is a document-style web service by using the @javax.jws.SOAPBinding annotation . We used the @javax.jws.WebMethod annotation to expose the addBid method in the web service . You can use the @javax.jws.WebResult and @javax.jws.WebParam annotations to control the parameter names generated in the WSDL.


Note

Using the @WebService annotation creates a stateless EJB to a web service. The rest of the annotations are optional.


In this section you’ll learn how to use web services metadata annotations. We’ll start with using the @WebService annotation to convert an EJB to a web service. You’ll then see how to use the @SOAPBinding annotation to specify the web service style. You’ll also learn about other annotations, such as @WebMethod, @WebParam, and @WebResult.

15.3.1. Using the @WebService annotation

The @WebService annotation is used on a bean or an interface class. If you use this annotation on the bean class, the annotation processor or the EJB container will generate the interface for you. If you already have a bean interface, then you can mark the @WebService annotation on the interface and the bean class will look like this:

@WebService
public interface PlaceBidWS {
public Long addBid(String bidderId, Long itemId, Double bidPrice);
}

@Stateless(name = "PlaceBid")
public class PlaceBidBean implements PlaceBidWS, PlaceBid {
...
}

If you use the @WebService annotation on the interface, then all public methods on the web service endpoint will be exposed in the web service. In our example we have only one method (addBid), and it will be exposed in the web service.

A careful look at the code reveals that the @WebService endpoint interface looks similar to the remote interface. You might be tempted to mark the same interface as both a web service and a remote interface, like this:

@WebService
@Remote
public interface PlaceBid {
public Long addBid(String bidderId, Long itemId, Double bidPrice);
}

Unfortunately, although some vendors allow this as an extension, this is not part of the specification, and code that uses this particular attribute combination won’t be portable.

Next, let’s take a peek at how you can use different elements of the @WebService annotation to customize different elements in your WSDL. Listing 15.3 shows the details of the @WebService endpoint interface.

Listing 15.3. Elements of the @WebService annotation

All elements on the @WebService annotation besides wsdlLocation and endpointInterface are used to customize the WSDL generation. wsdlLocation is useful when you are following a meet-in-the-middle approach and you want to use a pre-existing WSDL. It defines the URL for the WSDL; for example:

@WebService(wsdlLocation = "META-INF/myPlaceBidService.wsdl")
public interface PlaceBidWS {
public Long addBid(String bidderId, Long itemId, Double bidPrice);
}

When you specify wsdlLocation, the server will use the WSDL specified. If there are any inconsistencies between the existing WSDL and the implementation class, the container will generate the corresponding deployment errors.

As stated earlier, the server automatically generates the service endpoint interface (SEI) if the @WebService annotation is used in the bean class. This generated name is vendor specific, and most of the time that works just fine. If you find yourself needing to specify the endpointInterface element to use a specific name, try this:

@WebService(endPointInterface = "actionbazaar.buslogic.PlaceBidSEI")
@Stateless(name = "PlaceBid")
public class PlaceBidBean implements placeBid{}

Use the name element in the @WebService annotation to specify the name of the web service. If you don’t specify the name element, the name of the bean class or interface will be used by default. This is the same as the name attribute in the portType tag in the WSDL. In our example, the server will use the name PlaceBidBean because of the following setting:

<portType name = "PlaceBidBean">
...
</portType>

You can use the targetNamespace element to specify the target namespace for the WSDL elements generated by the web service. If you don’t specify this element, the EJB container will use the Java package name to generate a default XML namespace.

You can use the serviceName element to specify the service name. Specifying the serviceName is only allowed when you annotate the bean class. The name specified using serviceName is used for generating the name attribute in the service element in the WSDL. If you don’t specify the serviceName element, the server will generate it using the default, which is the bean class name appended with Service.

<service name = "PlaceBidBeanService">
...
</service>

This code snippet shows what happens if the serviceName isn’t specified for the PlaceBidBean EJB. The bean name PlaceBidBean is concatenated with Service by the WSDL generator, and PlaceBidBeanService is specified as the name of the web service in the WSDL.

Similarly, you use the portName element to set the name of the port specified in the WSDL.

15.3.2. Specifying the web service style with @SOAPBinding

As discussed earlier, the two types of services supported are document-oriented or RPC-oriented web services. You can use the @javax.jws.SOAPBinding annotation to control the style of the web service. This example shows the @SOAPBinding annotation in action:

@WebService(targetNamespace = "urn:ActionBazaarPlaceBidService")
@SOAPBinding(style = SOAPBinding.Style.RPC,
use = SOAPBinding.Use.ENCODED,
parameterStyle = SOAPBinding.ParameterStyle.BARE)
@Stateless(name = "PlaceBid")
public class PlaceBidBean implements PlaceBid {
}

Now let’s consider the various elements of the @SOAPBinding annotation and how they work. These elements are defined in listing 15.4.

Listing 15.4. Elements of the @SOAPBinding annotation

You can use the style element to define the web service style. Valid values are DOCUMENT and RPC in listing 15.4. The default style is DOCUMENT. You can specify the use element to configure the messaging style with one of the valid values, LITERAL or ENCODED . You must use the LITERAL style of messaging if you expect your services to work with clients not developed by you, because SOAP encoding can cause problems with interoperability of web services and therefore is not allowed by the WS-I Basic Profile 1.1. You can specify parameterStyle to configure how message parameters are specified. The valid values for parameterStyle are BARE and the default, WRAPPED .

15.3.3. Using @WebMethod

You can apply the @javax.jws.WebMethod annotation on a method to expose it as part of the web service. If you have multiple methods in the bean implementation class and you use a generated endpoint interface, you must annotate @WebMethod on the methods you want to expose in the web service. The following listing shows the details of the @WebMethod annotation:

@Target({METHOD})
public @interface WebMethod {
String operationName() default "";
String action() default "" ;
boolean exclude() default false;
};

If you don’t use the @WebMethod annotation, all public methods in the bean class that use a generated interface will be exposed in the web service. There are several reasons why this may not be a good idea. First, it is inefficient to have fine-grained web service methods. Like EJBs, web services should be coarse-grained. Second, it might create a tight coupling between your server and potential clients.


Note

If you use the @WebMethod annotation on an endpoint interface, your server will ignore it and expose all methods of the endpoint interface in the web service.


If you have multiple methods in the bean class and there are methods that you don’t want to expose in the web service, you can set the exclude element to true as follows:

@WebService(endPointInterface = "PlaceBidSEI")
@Stateless
public class PlaceBidBean {
public Long addBid(..) {
}

@WebMethod(exclude = "true")
public Long persistBid(..) {
}
}

Using this technique, the persistBid method will not be exposed in the web service when the PlaceBid EJB web service is deployed.

You can use the operationName and action elements in the @WebMethod annotation to specify the operation and SOAP action, respectively, as in the following example.

@WebMethod(operationName = "addNewBid",
action = "http://actionbazaar.com/NewBid")
public Long addBid(...) {
}

The operationName, as defined above the addBid method, will generate the following WSDL:

<portType name = "PlaceBidBean">
<operation name = "addNewBid">
...
</operation>
</portType>

Notice how the actual method name is addBid but the method named exposed in the web service is addNewBid. You can use this to help map the service contract to the actual implementation. Even if that implementation changes over time, the contract can remain intact. If the operationName isn’t specified, it will default to the implementation name of the method.

Similarly, the action element we defined earlier will be used for generating the SOAPAction in the WSDL as follows:

<operation name = "addNewBid">
<soap:operation soapAction = "http://actionbazaar.com/NewBid"/>
...
</operation>

The SOAPAction element determines the header element in the HTTP request message. It is used by the web service client when communicating with the web service using SOAP over HTTP. The content of the SOAPAction header field is used by the endpoint to determine the true intended destination rather than having to parse the SOAP message body to find this information.

This section gave you a tour of the @WebMethod annotation so you know how to define the method name for a web service. Next we’ll look at how to define parameters for our new web methods with the @WebParam annotation.

15.3.4. Using the @WebParam annotation

You can utilize the @javax.jws.WebParam annotation in conjunction with @WebMethod to customize a parameter for the web service message part generated in the WSDL. You saw a simple use of @WebParam in the PlaceBid EJB web service in section 15.3; here is a more comprehensive example:

@WebMethod
public Long addBid(
@WebParam(name = "user",
mode = WebParam.Mode.IN) String userId, ...) {
...
}

Let’s break this example down by looking at this annotation’s details. The specification for the @WebParam annotation looks like this:

@Target({PARAMETER})
public @interface WebParam {
public enum Mode { IN, OUT, INOUT };
String name() default "";
String targetNamespace() default "";
Mode mode() default Mode.IN;
boolean header() default false;
String partName() default "";
};

The name element can specify the name parameter for the message in the WSDL. If you do not specify name, the default value generated will be the same as the name of the argument.

You can use the targetNamespace element for customizing the XML namespace for the message part. If you do not specify targetNamespace, the server will use the namespace used for the web service.

The mode element will work to specify the type of the parameter. Valid options are IN, OUT, or INOUT (both). This mode determines how the parameter is flowing. If you specify a parameter as OUT or INOUT, the argument must be of type javax. xml.ws.Holder as follows:

@WebParam(name = "user", mode = WebParam.Mode.INOUT)
Holder<String> userId, ...) {
...
}

The holder class provides a reference to immutable object references. You can use a Java generic holder type, javax.xml.ws.Holder<String>, which is defined by the Java XML web services specification. The details of Holder types are not within the scope of this book; for more details, refer to the Java XML WS 2.0 specification.

You can set the header element to true if the message is pulled from the header of the message and not from the message body.

As we discussed earlier, you can pass any optional information (such as security) that isn’t part of the actual message in the SOAP header. When a SOAP message is exchanged between parties, it may go through several intermediaries, such as an authentication system. These intermediaries are not supposed to read the actual payload or message body, but are allowed to read the SOAP header. Setting header to true will generate the WSDL with the SOAP header as follows:

<operation name = "addNewBid">
<soap:operation soapAction = "urn:NewBid"/>
<input>
<soap:header message = "tns:PlaceBid_addNewBid"
part = "user"
use = "literal"/>
<soap:body use = "literal" parts = "parameters"/>
</input>
...
</operation>

You can use the partName element to control the generated name element of the wsdl:part or XML schema element of the parameter, if the web service binding style is RPC, or if the binding style is document and the parameter style is BARE. If you don’t specify the name for an RPC-style web service and partName is specified, the server will use partName to generate the name of the element.

15.3.5. Using the @WebResult annotation

The @WebResult annotation is very similar to @WebParam. It operates in conjunction with @WebMethod to control the generated name for the message return value in the WSDL, as illustrated here:

@WebMethod
@WebResult(name = "bidNumber")
public Long addBid(...){}

The @WebResult annotation specification resembles the specification for @WebParam. You’ll notice it’s a bit smaller, though, because you have less control over return values than you do over parameters.

public @interface WebResult {
String name() default "return";
String targetNamespace() default "";
boolean header() default false;
String partName() default "";
};

The name element specifies the name of the value returned in the WSDL.

Use the targetNamespace element for customizing the XML namespace for the returned value. This works for document-style web services where the return value binds to an XML namespace. If you don’t specify targetNamespace, the server will use the namespace allocated for the web service.

You can set the header element to true if the return value is returned as a part of the message header.

As with the @WebParam annotation, you have to use the partName argument to customize the name of value returned from an operation.

15.3.6. Using @OneWay and @HandlerChain

The web services metadata annotation specification defines two more annotations: @OneWay and @HandlerChain. We’ll briefly introduce them, and we encourage you to explore them if you think you need to. The @OneWay annotation is used with a web service operation that does not have a corresponding output (return value). It can be used on a method as follows:

@WebMethod
@OneWay
public void pingServer() {
}

In this case, pingServer doesn’t return anything and @OneWay optimizes the message to reflect this.

The @HandlerChain annotation is used to define a set of handlers that are invoked in response to a SOAP message. Logically, handlers are similar to EJB interceptors that were discussed earlier in part 2 of this book. Handlers are defined in an XML file. It probably makes sense to align interceptor annotations and web services handlers in a future release of Java EE, and use the interceptor programming model for JAX-WS handlers. Also, it’s worth mentioning that in an EJB web service, both EJB 3 interceptors and message handlers will fit the bill.


Tip

If you are using both JAX-WS handlers and interceptors in the same web service, invoking InvocationContext.getContextData() in the interceptor or WebServiceContext.getMessageContext() in the JAX-WS handler will return the same Map instance.


This concludes our discussion of web service metadata. The metadata makes development of EJB 3 web services very easy. You can essentially just annotate the bean class with @WebService and it automagically converts it to an EJB web service. Is this a huge improvement over the previous approach, or what?

Exposing a web service is one thing. What about consuming a web service? Is being on the client end of the web service connection easier with EJB 3? The next section walks you through using an EJB 3 session bean as a client to a web service. We think after you’ve read it you just may answer the previous question with a resounding yes!

15.4. Accessing a web service from an EJB

The first step to building a web service is to publish some standalone services that can be used by interested parties. But there’s a whole lot more to building an SOA than that. You’ll need to move to level 2 (to borrow terminology used in the gaming world). The next level of web services involves building aggregate services. This is where two or more services are combined to provide an even more coarse-grained functionality.

Of course, there is the simpler case where the service you expose simply needs to leverage a service not built by you. Either way, you’re the client in this scenario, so let’s see what’s involved in invoking web services from EJB 3. First we’ll examine a standalone Java client for testing the PlaceBid web service that we built in an earlier section; then we’ll explore how you can access a web service from an EJB such as a session bean or MDB.

15.4.1. Accessing the PlaceBid web service

An EJB web service doesn’t differ from any other web service and can be invoked by a client written in Java, .NET, or any other programming language. The client for the EJB web service can be any of the following types:

  • Java application client
  • Dynamic proxy
  • Dynamic Invocation Interface (DII)

Details about each of these clients are beyond the scope of this book. In this section, we’ll see an example of Java EE application client that uses the @WebServiceRef annotation to invoke the web service. Listing 15.5 shows an example of an application client invoking the PlaceBid web service that we built earlier.

Listing 15.5. Java application client accessing the PlaceBid web service

In listing 15.5, the client uses actionbazaarplacebidservice.PlaceBidService, which is the generated service interface . We use the @WebServiceRef annotation to inject a reference to the PlaceBid service by specifying the WSDL location . We retrieve the web service port from the injected web service by invoking the getPlaceBidBeanPort method . After we retrieve the port, we can invoke the operations allowed on the port . We’ll discuss @WebServiceRef in more depth in the next section. For now, all you need to know is that it is used to inject web service references.

If you use an application, as we did in our example, you must use the web services utility provided by your vendor to generate the client-side artifacts for accessing the web service. The tool reads the WSDL document and generates the endpoint interface and the proxy classes that can be used to invoke methods on the web service as a local object.

For example, the GlassFish/Java EE SDK provides utilities named wscompile or wsimport to generate the client-side proxy classes. Check out the build script (build.xml) of the online code samples for chapter 15 (www.manning.com/panda); in the sample provided for the Java EE 5 SDK (GlassFish) and you’ll see a task named gen-proxy:

<target name="gen-proxy" depends="setup">

<exec executable="${J2EE_HOME}/bin/${wsimport}" failonerror="true">
<arg line="-keep -d ${cli.proxy.dir} http://${admin.host}:
${http.port}/PlaceBidService/PlaceBidBean?WSDL"/>
</exec>
</target>

As you can see, wsimport takes the WSDL as input and generates the client-side artifacts, which includes the service interface and proxy classes. After compiling the client and other artifacts, you should be able to run the client to test the web service.

Now that you’ve seen an example web service client, let’s expand on the topic and see how you can access a web service.

15.4.2. EJB as a web service client

You can use either a session bean or an MDB to invoke a web service. For example, customers can track the status of items ordered from ActionBazaar. Internally, ActionBazaar uses the TrackOrder EJB to track this status. An external company, the Turtle and Snail Trucking Company, is used to ship the orders. The trucking company happens to be a heavy user of Microsoft technologies, and they provided a web service to track the status of orders. The TrackOrder EJB invokes this web service to check the delivery status of orders. The following code snippet of the TrackOrder EJB invokes a web service:

You learned from an earlier example that you can use @javax.xml.ws.WebServiceRef to reference and inject an instance of either the service class or endpoint interface. As you’ll recall, in listing 15.5 we used a generated service interface.

Injection of @WebServiceRef is supported only in managed classes. In our example we are injecting an endpoint , and then invoking a method on the endpoint interface . Optionally you can use @WebServiceRef to inject a service interface as follows:

@WebServiceRef
private TrackingService service;

If you’re using a service interface (TrackingService), then it must extend javax.xml.ws.Service. The service interface or endpoint interfaces and the client-side proxy classes can typically be generated either on the fly by tools or utilities provided with the SOAP stack. These vary by vendor.

Although the Turtle and Snail Trucking Company uses the .NET platform for developing the tracking web service, you can’t use that interface with the Java EE platform. Therefore, you have to generate the endpoint interface by using tools supplied by your vendor. You do this by pointing the tool at the WSDL of TrackDeliveryService.

The @WebServiceRef annotation is similar to @javax.annotation.Resource (which we discussed in chapter 5). You can use the @WebServiceRef annotation to establish a reference at the class level or use field/setter injection. Table 15.3 describes the various elements of the @WebServiceRef annotation.

Table 15.3. Elements of @WebServiceRef

Element

Description

name

The JNDI name for the web service. It gets bound to java:comp/env/<name> in the ENC.

wsdlLocation

The WSDL location for the service. If not specified, then it is derived from the referenced service class.

type

The Java type of the resource.

value

The service class; always a type extending javax.xml.ws.Service.

mappedName

Vendor-specific global JNDI name for the service.

This concludes our discussion of invoking a web service from an EJB. You’ve now seen how to expose your web service for potential clients to consume, as well as how to access other web services on the network regardless of what technology was used to develop them. The new JAX-WS 2.0 annotations make defining and working with web services significantly easier than previous web service standards.

Next we’ll discuss some best practices you can use to build web services that maximize their interoperability opportunities.

15.5. Best practices for web service development

In this section we outline some of the best practices for building web services.

Determine whether you really need your application to be exposed as a web service and that your application requires interoperability. If not, then consider using alternative technologies and protocols because you will most likely find better performance in using alternative protocols such as RMI. Regardless of the technology used, at this point in the SOAP web service paradigm, messing around with all that XML can put a real strain on your network. Options for sending binary web service messages are just now emerging, but they are still a few years away from being widely available.

So the first recommendation is for you not to expose all your EJBs as web services. In addition, whenever considering methods to expose, only expose coarse-grained EJBs as web services. Either build a service endpoint interface for your EJB, or use the @WebMethod annotation to limit the methods exposed in the web service.

Analyze whether you need RPC-oriented or document-oriented web services. You can use the @SOAPBinding annotation to control the style for your EJB web service. RPC-style web services may perform better than document style web services. However, document style web services provide more flexibility because you can use XML schemas to define the messages. Similarly, avoid using message encoding because it makes your services less interoperable, as well as less portable between SOAP implementations. Document/literal is the recommended combination for an interoperable web service.

Design your EJB web service so that it creates very minimal network traffic. Avoid sending large objects over the wire. It’s better to send an Id or reference to an object instead of sending the entire object. All objects sent via SOAP are serialized into XML. The XML representation of data can be quite large, making SOAP messages much more expensive than retrieving the object in the target location. In addition, if your EJB involves a long-running transaction, avoid exposing it as a web service, or mark it as not returning a value so that it can be invoked in a more asynchronous manner.

Use JAX-WS data types as the method parameters for your web service to give it interoperability with heterogeneous web services. Suppose you have an object graph involving Collections, HashMaps, and Lists as web service parameters. Using these data types in the WSDL makes your application less interoperable. Test your applications to make sure they comply with the WS-I Basic Profile if interoperability is important for your application.

There are several mechanisms to secure your web services. You must weigh your security requirements against performance, because security comes with a high cost. The performance costs of end-to-end security are commonly higher than the initial perceived costs. This is true in general of system/application security, but even more so with regard to web services that are designed to be shared with unknown client applications.

15.6. Summary

In this chapter you learned how to expose a stateless session bean as a web service. First, we walked through a brief review of web service components and approaches to web service development. You saw that web service metadata greatly simplifies the development of EJB 3 web services by turning an EJB into a web service using one annotation: @WebService. JAX-WS 2.0–compliant containers dynamically generate endpoint interfaces, WSDL, and mapping files, and don’t require that you perform the mundane task of packaging several deployment descriptors and mapping files. You saw that different annotations supported by web services metadata can be used for controlling specific elements of the WSDL. It’s also possible to use an existing WSDL with an EJB 3 web service.

EJB 3 web services provide several benefits compared with regular Java class web services, although there is hardly any difference in coding style.

Your EJB application may require invoking a web service, and you can use either a SEI or service interface via the @WebServiceRef annotation.

Finally, we reviewed some best practices in using EJB 3 with web services. Following these guidelines can make your web services more interoperable and better performing.