Defining a Web Service with JAX-RPC






Defining a Web Service with JAX-RPC

Java EE provides two different programming models for defining a JAX-RPC web service: the web container model (or servlet model) and the EJB container model. Given that this book is about EJB 3.0, we assume you are more interested in the EJB model.

The core component in the EJB model is called an EJB endpoint . An EJB endpoint is a stateless session bean that is exposed as a web service. In addition to the remote and local component interfaces, there is another component interface, called the service endpoint interface . The service endpoint interface defines the abstract web services contract that the EJB endpoint provides to a web services client.

Because an EJB endpoint is simply a SOAP-accessible stateless session bean, it has the same advantages as other EJBs. An EJB endpoint runs in the same EJB container that automatically manages transactions and security and provides access to other EJBs and resources via injection or the JNDI ENC.

To illustrate how an EJB endpoint is developed, we'll create a new version of the TravelAgent EJB. The revised TravelAgent EJB will use the same logic as the TravelAgent EJB developed in Chapter 11 and the ReservationProcessor EJB developed in Chapter 12, but it will be deployed as a stateless session bean with an endpoint interface. The TravelAgent endpoint is based on the WSDL document shown earlier in this chapter.

The WSDL Document

Every EJB endpoint must have a WSDL document that describes the web service. You can create this document by hand, or you can use the tools provided by your Java EE vendor to generate it. The <portType> declared by the WSDL document must be aligned with the endpoint interface of the web service. In other words, the mapping between the WSDL <portType> and the endpoint interface must be correct according to the JAX-RPC specification. One way to ensure this is to create the WSDL document first, and then use it to generate the service endpoint interface:

<?xml version="1.0"?>
<definitions name="TravelAgent"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:titan="http://www.titan.com/TravelAgent"
   targetNamespace="http://www.titan.com/TravelAgent">

<!-- message elements describe the parameters and return values -->
<message name="RequestMessage">
   <part name="cruiseId"   type="xsd:int" />
   <part name="cabinId"    type="xsd:int" />
   <part name="customerId" type="xsd:int" />
   <part name="price"      type="xsd:double" />
</message>
<message name="ResponseMessage">
   <part name="reservationId" type="xsd:string" />
</message>

<!-- portType element describes the abstract interface of a web service -->
<portType name="TravelAgentEndpoint">
  <operation name="makeReservation">
     <input message="titan:RequestMessage"/>
     <output message="titan:ResponseMessage"/>
  </operation>
</portType>

<!-- binding element tells us which protocols and encoding styles are used -->
<binding name="TravelAgentBinding" type="titan:TravelAgentEndpoint">
   <soap:binding style="rpc"
                 transport="http://schemas.xmlsoap.org/soap/http"/>
   <operation name="makeReservation">
      <soap:operation soapAction="" />
      <input>
        <soap:body use="literal"
              namespace="http://www.titan.com/TravelAgent"/>
      </input>
      <output>
        <soap:body use="literal"
              namespace="http://www.titan.com/TravelAgent"/>
      </output>
   </operation>
</binding>

<!-- service element tells us the Internet address of a web service -->
<service name="TravelAgentService">
  <port name="TravelAgentPort" binding="titan:TravelAgentBinding">
     <soap:address location="http://www.titan.com/webservices/TravelAgent" />
  </port>
</service>

</definitions>

The Service Endpoint Interface

The process for generating a service endpoint interface for an EJB endpoint is identical to the process we used to generate a JAX-RPC client. The JAX-RPC compiler generates it from the <portType> and <message> definitions (and <types>, if present). The resulting interface looks like the following:

package com.titan.webservice;

public interface TravelAgentEndpoint extends java.rmi.Remote {
    public java.lang.String makeReservation(int cruiseId, int cabinId,
                                            int customerId, double price)
                            throws java.rmi.RemoteException;
}

Alternatively, you can start from Java by writing the service endpoint interface by hand. You can then generate the WSDL and the JAX-RPC mapping file from this interface. Refer to Figure, earlier in the chapter, to determine the schema types that will be mapped from the Java parameters in each method.

The Stateless Bean Class

The bean class defined for the TravelAgent endpoint must implement the methods defined by the endpoint interface. As with remote and local interfaces, a stateless bean class can implement the service endpoint interface directly. Here's the new definition for the travelAgentBean class:

package com.titan.webservice;
import com.titan.domain.*;
import com.titan.cabin.*;
import com.titan.processpayment.*;
import javax.ejb.EJBException;
import java.util.Date;
import java.util.Calendar;
import javax.persistence.*;

@Stateless
public class TravelAgentBean implements TravelAgentEndpoint {
    @PersistenceContext EntityManager em;

    @EJB ProcessPaymentLocal process;

    public String makeReservation(int cruiseId, int cabinId,
                                  int customerId, double price){
      try {
            Cruise cruise = em.find(Cruise.class, cruiseId);
            Cabin cabin = em.find(Cabin.class, cabinId);
            Customer customer = em.find(Customer.class, customerId);
            CreditCardDO card = this.getCreditCard(customer);

            Reservation reservation = new Reservation(
                       customer, cruise, cabin, price, new Date( ));
            process.byCredit(customer, card, price);

            return reservation.getId( );

        } catch(Exception e) {
            throw new EJBException(e);
        }
    }

    public CreditCardDO getCreditCard(Customer cust) throws Exception{
        CreditCard card = customer.getCreditCard( );
        return new CreditCardDO(card.getNumber(),card.getExpirationDate( ),
                                card.getCreditOrganization( ));
    }
}

The TRavelAgentBean class is not that different from the TravelAgent EJB developed earlier in this chapter (the version that uses the Charge-It credit card processing web service). The primary differences are that it responds to web service calls rather than remote or local calls, and it is a stateless session bean rather than a stateful session bean.

The Deployment Files

The TravelAgent endpoint requires three deployment files: a WSDL file, a JAX-RPC mapping file, and a webservices.xml file. In this section, we will create these files manually, although you would typically use the tools provided by your Java EE implementation to assist in this process.

The WSDL file

The WSDL file used to represent the endpoint interface must be packaged with the EJB endpoint. Normally, the WSDL document is placed in the META-INF directory of the JAR file, but it can go anywhere as long as it's in the same JAR file as the EJB endpoint.

The JAX-RPC mapping file

EJB endpoints, like JAX-RPC service references, require you to define a JAX-RPC mapping file. The mapping file can have any name, but it should be descriptive, and the file type should be XML. It's common to name this file jaxrpc-mapping.xml or travelagent_mapping.xml, or something along those lines. We covered the JAX-RPC mapping file earlier in this chapter in the section titled "The JAX-RPC Mapping File."

The webservices.xml file

The webservices.xml file is the baling wire that ties the separate deployment files together. It defines the relationships between the stateless session bean, the WSDL file, and the JAX-RPC mapping file:

<?xml version='1.0' encoding='UTF-8' ?>
<webservices
   xmlns="http://java.sun.com/xml/ns/j2ee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:titan="http://www.titan.com/TravelAgent"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                 http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd"
   version="1.1">

      <webservice-description>
         <webservice-description-name>TravelAgentService
         </webservice-description-name>
         <wsdl-file>META-INF/travelagent.wsdl</wsdl-file>
         <jaxrpc-mapping-file>/META-INF/travelagent_mapping.xml
         </jaxrpc-mapping-file>
         <port-component>
            <port-component-name>TravelAgentEndpoint</port-component-name>
            <wsdl-port>titan:TravelAgentPort</wsdl-port>
            <service-endpoint-interface>
               com.titan.webservice.TravelAgentEndpoint
            </service-endpoint-interface>
            <service-impl-bean>
               <ejb-link>TravelAgentBean</ejb-link>
            </service-impl-bean>
         </port-component>
      </webservice-description>
</webservices>

The <webservice-description> element describes an EJB endpoint; there may be one or more of these elements in a single webservices.xml file.[*] <webservice-description-name> is a unique name assigned to the web services description. It can be anything you like. The <wsdl-file> element points to the WSDL document of the EJB endpoint. Each EJB endpoint has exactly one WSDL document, which is usually located in the META-INF directory of the EJB-JAR file. When the EJB endpoint is deployed, your deployment tool will probably provide you with the option of copying the WSDL document to some type of public URL or registry so that others can discover the web service. The <jaxrpc-mapping-file> element indicates the location of the JAX-RPC mapping file that is associated with the EJB endpoint and the WSDL document. It, too, is usually located in the META-INF directory of the EJB-JAR file.

[*] The <webservice-description> element can also describe a JAX-RPC service endpoint, which is a servlet-based web service that is outside the scope of this book.

The <port-component> element maps a stateless session bean declared in the ejb-jar.xml file to a specific <port> in the WSDL document. <port-component-name> is the logical name you assign the EJB endpoint. It can be anything. The <wsdl-port> element maps the EJB endpoint deployment information to a specific WSDL <port> element in the WSDL document. <service-endpoint-interface> is the fully qualified name of the endpoint interfaceit must be the same interface declared by the <service-endpoint> element for the EJB in the ejb-jar.xml file. <service-impl-bean> and its <ejb-link> element link the <port-component> to a specific EJB. The value of <ejb-link> must match the value of the EJB name, which is travelAgentBean in this example.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows