16.3. Serving Web Services from Geronimo

Geronimo supports web services running as either servlets or EJBs (Stateless Session Beans). The configuration is slightly different, but both approaches use the same interfaces, WSDL, and JAX-RPC mapping file as described for the example in Section 16.2, “A Sample Web Service”.

16.3.1. The webservices.xml Configuration File

Both servlet and EJB web services require a standard webservices.xml file to provide the locations of the WSDL and JAX-RPC mapping files as well as to map a specific port from the web service to the combination of a service endpoint interface and a specific EJB or Servlet. A webservices.xml file for the sample web service might look like this:

<?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"
       xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
   http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd"
       xmlns:ger="geronimo-book:reviews"
       version="1.1">
  <webservice-description>
    <webservice-description-name>
      ProductReviews
    </webservice-description-name>
    <wsdl-file>META-INF/ReviewService.wsdl</wsdl-file>
    <jaxrpc-mapping-file>
      META-INF/ReviewServiceMapping.xml
    </jaxrpc-mapping-file>
    <port-component>
      <port-component-name>ProductReviews</port-component-name>
      <wsdl-port>ger:ProductReviews</wsdl-port>
      <service-endpoint-interface>
        reviews.ProductReviews
      </service-endpoint-interface>
      <service-impl-bean>
        <ejb-link>ReviewManager</ejb-link>
      </service-impl-bean>
    </port-component>
  </webservice-description>
</webservices>

Though this example is for an EJB, the webservices.xml file for a servlet-based web service would be quite similar:

  • The file paths would typically begin with WEB-INF instead of META-INF, though these locations are not required.

  • The service-impl-bean would contain a servlet-link pointing to a servlet, instead of an ejb-link pointing to an EJB.

The other difference is that the webservices.xml file is saved under META-INF in an EJB JAR, or under WEB-INF in a web application WAR.

[Warning]Warning

In Geronimo 1.0, the wsdl-file and jaxrpc-mapping-file values in this file should not begin with a / or else they will not be loaded correctly.

16.3.2. Servlet-based Web Services

For a web services based on a servlet, an implementation of the service endpoint interface must be provided. It does not actually need to be a servlet, it just needs to implement the service endpoint interface. It does run as a web component, so it has access to the JNDI environment configured for the web application and so on.

16.3.2.1. The Service Implementation Class

A sample service implementation class corresponding to the sample ProductReviews service endpoint interface might look like this:

package reviews.server;

import javax.xml.rpc.server.ServiceLifecycle;
import javax.xml.rpc.server.ServletEndpointContext;
import javax.xml.rpc.ServiceException;
import reviews.ProductReviews;

public class ServletProductReviews implements ProductReviews, ServiceLifecycle {
    public String[] getReviewers(Integer productId) {
        ...
    }

    public ReviewData[] getReviews(Integer productId) {
        ...
    }

    public ReviewData getReview(Integer productId,
                                String reviewer) {
        ...
    }

    public void init(Object object) throws ServiceException {
        ServletEndpointContext ctx = (ServletEndpointContext)object;
    }

    public void destroy() {
    }
}

This example also implements ServiceLifecycle, which is optional and provides the init and destroy methods for the service implementation.

16.3.2.2. Declaring the Service in web.xml

The service implementation is declared as a servlet, even though technically it is not a servlet (the entries in webservices.xml are used to figure out which Servlet declarations are allowed to not implement javax.servlet.Servlet). It requires a single servlet mapping entry, which (when added to the context path for the web application as a whole) overrides the URL path provided for the servlet in the WSDL. So the additional content in web.xml might look like this:

    <servlet>
        <servlet-name>ProductReviewsService</servlet-name>
        <servlet-class>reviews.server.ServletProductReviews</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ProductReviewsService</servlet-name>
        <url-pattern>/ProductReviews</url-pattern>
    </servlet-mapping>

16.3.2.3. Security Settings

As part of the web application, the service is covered by the security settings applied to the web application as a whole. This means specific roles or transport guarantees may be applied by restricting access to the URL where the service is listening, and the service will use the same security realm as the rest of the web application.

[Warning]Warning

Web services do not support form-based authentication, so the web application should use BASIC, DIGEST, or CLIENT-CERT authentication for secure web services.

16.3.2.4. Packaging Requirements

For a servlet based web service, the following files must be included in the web application WAR:

  • The service endpoint interface class should be included like any other servlet classes

  • The service implementation class should be included like any other servlet class

  • The WSDL file should be included in the WAR (any location is fine, though somewhere under WEB-INF is typical)

  • The JAX-RPC mapping file should be included in the WAR (any location is fine, though somewhere under WEB-INF is typical)

  • The WEB-INF/webservices.xml file (described in Section 16.3.1, “The webservices.xml Configuration File”) must be included in the WAR, providing the locations of the previous 2 files.

16.3.2.5. Deployment

A web application WAR including web services is deployed the same as any other WAR, whether in an EAR or standalone. Additional validation and code generation is performed during deployment, so new errors may crop up (typically caused by errors in the WSDL or JAX-RPC mapping files).

16.3.2.6. Accessing the Service

The host and port to reach the service are generated from the Geronimo web listener configuration. The path information used to reach the service is set using the servlet-mapping element in the web.xml deployment descriptor. In addition, the WSDL for the service can be found by adding ?wsdl to the end of the web service URL (and it updates the service URL in the WSDL it provides according to the listen host, port, and path).

Example 16.2. Contacting a Servlet Web Service

The web.xml example above contained a servlet mapping assigning the web service to /ProductReviews. Assuming the web application itself was mapped to the context /test, the service could be accessed at:

Service

http://localhost:8080/test/ProductReviews

WSDL

http://localhost:8080/test/ProductReviews?wsdl

These URLs would be the same even if the URL in the WSDL was changed to something arbitrary.

16.3.3. Session Bean based Web Services

For a web service based on a session bean, the bean declares the service endpoint interface just like it would declare a remote or local interface (there is no equivalent of a home interface for a web service). The service calls are handled by the session bean implementation class, so the bean class must have all the methods that are in the service endpoint interface (except the implementation methods should not throw RemoteException).

16.3.3.1. The Session Bean Implementation Class

A sample session bean implementation class corresponding to the sample ProductReviews service endpoint interface might look like this:

public class ReviewManagerBean implements javax.ejb.SessionBean {
    public void ejbCreate() throws javax.ejb.CreateException {}

    public void setSessionContext(javax.ejb.SessionContext ctx)
                                throws javax.ejb.EJBException {}

    public void ejbRemove() throws javax.ejb.EJBException {}

    public void ejbActivate() throws javax.ejb.EJBException {}

    public void ejbPassivate() throws javax.ejb.EJBException {}

    public String[] getReviewers(Integer productId) {
        ...
    }

    public ReviewData[] getReviews(Integer productId) {
        ...
    }

    public ReviewData getReview(Integer productId,
                                String reviewer) {
        ...
    }
}

Note that the bean class may have additional methods, including methods exposed via the local or remote interfaces but not the service endpoint interface. But it must at a minimum have all the methods required of session beans as well as the methods in the service endpoint interface.

16.3.3.2. A Web Service in ejb-jar.xml

The service endpoint interface is added to the block for the session bean in ejb-jar.xml like this:

<session>
  <ejb-name>ReviewManager</ejb-name>
  <local-home>review.ejb.ReviewManagerHome</local-home>
  <local>review.ejb.ReviewManager</local>
  <service-endpoint>reviews.ProductReviews</service-endpoint>
  <ejb-class>review.ejb.ReviewManagerBean</ejb-class>
  <session-type>Stateless</session-type>
  <transaction-type>Container</transaction-type>
</session>

16.3.3.3. Web Service Security and URL Configuration

The Geronimo EJB deployment descriptor can be used to customize the settings for the web service, including security options as well as the URL that the service is bound to. Full details of the available settings can be found in Section 12.3.3.1, “Session Beans as Web Services”.

Example 16.3. Session Bean Web Service Customization

This block from openejb-jar.xml indicates that the service should be bound to the path /services/Review instead of whatever the WSDL might have specified, it should require SSL, and it should use HTTP Basic authentication for security and authenticate against the Geronimo realm geronimo-properties-realm.

<session>
  <ejb-name>ProductReviewManager</ejb-name>
  <web-service-address>/services/Review</web-service-address>
  <web-service-security>
    <security-realm-name>
      geronimo-properties-realm
    </security-realm-name>
    <realm-name>Product Review Service</realm-name>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    <auth-method>BASIC</auth-method>
  </web-service-security>
</session>

16.3.3.4. Packaging Requirements

For a session bean based web service, the following files must be included in the EJB JAR:

  • The service endpoint interface class should be included like any other EJB classes

  • The session bean implementation class should be included like normal

  • The WSDL file should be included in the EJB JAR (any location is fine, though somewhere under META-INF is typical)

  • The JAX-RPC mapping file should be included in the EJB JAR (any location is fine, though somewhere under META-INF is typical)

  • The META-INF/webservices.xml file (described in Section 16.3.1, “The webservices.xml Configuration File”) must be included in the EJB JAR, providing the locations of the previous 2 files.

16.3.3.5. Deployment

An EJB JAR including web services is deployed the same as any other EJB JAR, in an EAR or standalone. Additional validation and code generation is performed during deployment, so new errors may crop up (typically caused by errors in the WSDL or JAX-RPC mapping files).

16.3.3.6. Accessing the Service

If the WSDL specifies a valid URL for the service, then the service is normally bound to that address (in truth, the host and port are ignored but the service is bound based on the path information present in the URL). Otherwise, the path information can be overridden using the web-service-address element in the Geronimo deployment plan for the EJB.

In either case, the WSDL for the service can be found by adding ?wsdl to the end of the web service URL (and it updates the host and port in the WSDL it provides to use whatever host and port you used to retrieve the WSDL).

Example 16.4. Contacting an EJB Web Service

The sample web service included the following block in the WSDL:

  <wsdl:service name="ProductReviewsService">
    <wsdl:port name="ProductReviews"
               binding="ger:ProductReviewsSoapBinding">
      <wsdlsoap:address
  location="http://localhost:8080/test/services/ProductReviews"/>
    </wsdl:port>
  </wsdl:service>

With a configuration like that, the service can be accessed at:

Service

http://localhost:8080/test/services/ProductReviews

WSDL

http://localhost:8080/test/services/ProductReviews?wsdl

These URLs would be the same even if the host and port were changed to something arbitrary in the WSDL.