In this recipe, we will demonstrate how to create a JAX-WS application based on a stateless session EJB. There are several variations on how this can be done, however, they all use a class as the web service and embed other session EJBs to provide the web service's functionality. Stateless and singleton session beans can be used as endpoints. As of EJB 3.1, stateful session beans can also be used for endpoints.
The two fundamental steps involved in the creation of a JAX-WS web service include:
The creation of the EJB is detailed in earlier chapters, particularly Chapter 2, Session Beans that deals with session EJBs. The focus of this recipe is how to create the web service. To create a web service endpoint based on JAX-WS we need to:
Within the web service class methods we need to use the supporting EJB to implement the service's functionality.
To demonstrate the creation of a web service, we will use a CustomerManager
class which provides simple customer information. The EJB will support two methods: getCustomerCount
and getCustomerCountByRegion
. These methods are simple by design so as not to distract from the details of creating the web service.
Create a Java Web Application called CustomerApplication
. In NetBeans this type of project is found in the Java Web category of the New Project wizard. Go ahead and add three packages to the project's Source Packages folder though we will only be using two of them in this recipe.
packt
Holds the CustomerManager
classjaxws
Used for the JAX-WS web service classjaxrs
Used in the next recipe to hold the RESTful application classesNext, create the CustomerManager
stateless session bean in the packt
package. Add two methods:
To keep the application simple, the getCustomerCount
will always return 27. Implement the getCustomerCountByRegion
method such that when passed the string, "West", it will return 12 and when passed the string, "East", it will return 15. Otherwise, we will return 0 keeping the method simple. One possible implementation follows:
@Stateless public class CustomerManager { public int getCustomerCount() { return 27; } public int getCustomerCountByRegion(String region) { if("West".equals(region)) { return 12; } else if("East".equals(region)) { return 15; } else { return 0; } } }
This completes our session EJB. Now let's see what we need to do to create the actual web service. The basic steps we will use include:
Classes that act as a web service endpoint are designated with the @WebService annotation. A Service Endpoint Interface (SEI) is an interface that declares the endpoint's methods. An explicit interface is not required but can be specified using the @WebService endpointInterface element.
Create a class called Customer
in the jaxws
package. Annotate it using the @WebService annotation. In the class inject an instance of the CustomerManager
class and add getCustomerCount
and getCustomerCountByRegion
methods mimicking those of the CustomerManager
class.
Add the @WebMethod annotation to these two methods. In the getCustomerCount
method, use the CustomerManager's getCustomerCount
as the return value. In the getCustomerCountByRegion
method, use the region
parameter as the argument to the CustomerManager's getCustomerCountByRegion
method and return this value.
@WebService() public class Customer { @EJB private CustomerManager customerManager; @WebMethod public int getCustomerCount() { return customerManager.getCustomerCount(); } @WebMethod public int getCustomerCountByRegion (String region) { return customerManager.getCustomerCountByRegion(region); } }
To test this service, use the URL, http://localhost:8080/CustomerApplication/CustomerService?Tester with a browser. This should result in output similar to the following screenshot:
Execute both methods. Notice the resulting output shows a SOAP Request and SOAP Response further down in the browser's window. In the case of the second method, notice the name of the argument is arg0.
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns2:getCustomerCountByRegion xmlns:ns2="http://jaxws/">
<arg0>West</arg0>
</ns2:getCustomerCountByRegion>
</S:Body>
</S:Envelope>
In the There's more section we will see how we can control this name and other aspects of the service.
The @WebService annotation designated the class as a web service endpoint. Its serviceName element provided the name of the service as known to a client. In this case it was CustomerService
as used in the URL. Notice while our class name is Customer
, the string, "Service" was automatically appended to the class name. The @WebMethod designates a method available as part of the service. When these methods are invoked, they used the corresponding methods provided by the injected EJB CustomerManager
.
The getCustomerCount
method returned 27. We could have developed a more sophisticated application using a database and entity classes, however, the added sophistication would have distracted from the creation of the web service.
Actually, this additional functionality is where JAX-WS becomes more important. When issues such as security and transaction processing are an important part of an application, JAX-WS is a better choice than JAX-RS.
Here we will address the web service-related annotations in more depth:
The @WebService annotation has several elements permitting us to control the names used with the service. Here we are only interested in the serviceName element. Using this element allows us to use a name other than the default name provided for us, "CustomerService". Notice while our class name is Customer
, the string, "Service" is automatically appended to the class name. The serviceName element allows us to change the name of the service.
Modify the @WebService as shown below:
Use the following URL in place of the old one:
http://localhost:8080/CustomerApplication/Customer?Tester
Notice the behavior is the same.
Business methods of the web service interface must be declared as public
and cannot be declared as static
or final
. They are annotated with the @WebMethod annotation to designate them as endpoint methods.
Parameters of these methods must be JAXB-compatible. The Java Architecture for XML Binding (JAXB) is an API used to simplify access to XML documents. This API provides an alternative to using the Simple API for XML (SAX) or the Document Object Module (DOM) to access an XML document. A list of JAXB-compatible data types is found at: http://download.oracle.com/javaee/5/tutorial/doc/bnazq.html#bnazs.
To control the name of the method as exposed by the web service, we can use the operationName element of the @WebMethod annotation. For example, use the following @WebMethod annotation for the getCustomerCount
method:
When the application is executed you should see the new method name in the browser.
As pointed out earlier, the name of the getCustomerCountByRegion's
argument is arg0. While this is not necessarily a problem, we can control this name using the @WebParam annotation. Modify the getCustomerCountByRegion
method as shown below. This annotation specifies the web name of the parameter to be "region".
When the application is executed you should see the new parameter name in the SOAP Request message as shown here:
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns2:getCustomerCountByRegion xmlns:ns2="http://jaxws/">
<region>West</region>
</ns2:getCustomerCountByRegion>
</S:Body>
</S:Envelope>
The first three recipes in Chapter 2, Session Beans provide more detail about the use and creation of session EJBs.
3.136.17.12