Creating an EJB-based web service using JAX-WS

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.

Getting ready

The two fundamental steps involved in the creation of a JAX-WS web service include:

  1. Creating an EJB which provides the application's functionality
  2. Creating a Web Service (JAX-WS) which utilizes the EJB

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:

  1. Use the @WebService annotation to designate a class as an endpoint
  2. Annotate the methods of the service with the @WebMethod annotation

    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.

How to do it...

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 class
  • jaxws Used for the JAX-WS web service class
  • jaxrs Used in the next recipe to hold the RESTful application classes

Next, create the CustomerManager stateless session bean in the packt package. Add two methods:

  • getCustomerCount This method is passed void and returns an integer
  • getCustomerCountByRegion This method also returns an integer but is passed a string representing the region of interest.

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:

  1. Create an @WebService annotated class
  2. Inject the supporting EJB
  3. Create @WebMethod annotated methods to expose the desired web service functionality

    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:

    How to do it...

    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.

How it works...

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.

There's more...

Here we will address the web service-related annotations in more depth:

  • Variations of the @WebService annotation
  • Using the @WebMethod annotation
  • Using the @WebParam annotation

Variations of the @WebService annotation

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.

Using the @WebMethod annotation

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.

Using the @WebParam annotation

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>

See also

The first three recipes in Chapter 2, Session Beans provide more detail about the use and creation of session EJBs.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.136.17.12