Web Services with JOnAS

Starting with JOnAS 3.3, Web Services can be used within EJBs and/or servlets/JSPs. This integration conforms to the JSR 921(Web Service for J2EE v1.1) specification.

1. Web Services

A. Some Definitions

WSDL: WSDL (Web Service Description Language v1.1) is an XML-based format for specifying the interface to a web service. The WSDL details the service's available methods and parameter types, as well as the actual SOAP endpoint for the service. In essence, WSDL is the "user's manual" for the web service.
SOAP: SOAP (Simple Object Access Protocol v1.2) is an XML-based protocol for sending requests and responses to and from web services. It consists of three parts: an envelope defining message contents and processing, encoding rules for application-defined data types, and a convention for representing remote procedure calls and responses.
JAX-RPC: JAX-RPC (Java Api for XML RPC v1.1)  is the Java API for XML-based RPC. RPC (Remote Procedure Call) allows a client to execute procedures on other systems. The RPC mechanism is often used in a distributed client/server model in which the server defines a service as a collection of procedures that may be called by remote clients. In the context of Web services, RPCs are represented by the XML- based protocol SOAP when transmitted across systems.
In addition to defining envelope structure and encoding rules, the SOAP specification defines a convention for representing remote procedure calls and responses. An XML-based RPC server application can define, describe and export a web service as an RPC-based service. WSDL (Web Service Description Language) specifies an XML format for describing a service as a set of endpoints operating on messages. With the JAX-RPC API, developers can implement clients and services described by WSDL.

B. Overview of a Web Service

Strictly speaking, a Web Service is a well-defined, modular, encapsulated function used for loosely coupled integration between applications' or systems' components. It is based on standard technologies, such as XML, SOAP, and UDDI.

Web Services are generally exposed and discovered through a standard registry service. With these standards, Web Services consumers (whether they be users or other applications) can access a broad range of information -- personal financial data, news, weather, and enterprise documents -- through applications that reside on servers throughout the network.

Web Services use a WSDL Definition (refer to www.w3.org/TR/WSDL) as a contract between client and server (also called endpoint). WSDL defines the types to serialize through the network (described with XMLSchema), the messages to send and receive (composition, parameters), the portTypes (abstract view of a Port), the bindings (concrete description of PortType: SOAP, GET, POST, ...), the services (set of Ports), and the Port (the port is associated with a unique endpoint URL that defines the location of the Web Service).

A Web Service for J2EE is a component with some methods exposed and accessible by HTTP (through servlet(s)). Web Services can be implemented as Stateless Session Beans or as JAXRPC classes (a simple Java class, no inheritance needed).

WS endpoint
Figure 1. Web Services endpoints deployed within JOnAS (an external client code can access the endpoint via AxisServlet)
WS client
Figure 2. Web Services client deployed within JOnAS (can access external Web Services)

The servlet is used to respond to a client request and dispatch the call to the designated instance of servant (the SSB or JAXRPC class exposed as Web Service). It handles the deserialization of incoming SOAP messages to transform SOAP XML into a Java Object, perform the call, and serialize the call result (or the thrown exception) into SOAP XML before sending the response message to the client.


2. Exposing a J2EE Component as a Web Service

There are two types of J2EE components that can be exposed as Web Services endpoints: StateLess Session Beans and JAX-RPC classes. Web Services' Endpoints must not contain state information.

A new standard Deployment Descriptor has been created to describe Web Services endpoints. This Descriptor is named "webservices.xml" and can be used in a webapp (in WEB-INF/) or in an EjbJar (in META-INF/). This Descriptor has its JOnAS-specific Deployment Descriptor (jonas-webservices.xml is optional).

Refer to the webServices sample for example files.

A. JAX-RPC Endpoint

A JAX-RPC endpoint is a simple class running in the servlet container (Tomcat or Jetty). SOAP requests are dispatched to an instance of this class and the response is serialized and sent back to the client.
A JAX-RPC endpoint must be in a WebApp (the WAR file must contain a "WEB-INF/webservices.xml").

B. Stateless Session Bean Endpoint

An SSB is an EJB that will be exposed (all or some of its methods) as a Web Service endpoint.
In the ejb-jar.xml standard descriptor, a session bean, exposed as a web service, must now use the new service-endpoint tag. Here the developer defines the fully-qualified interface name of the web service. Notice that no other interfaces (home, remote, localhome, local) are needed with a session bean exposed as web service.

Typically, an SSB must be in an EjbJar, and a "META-INF/webservices.xml" is located in the EjbJar file.

C. Usage

In this Descriptor, the developer describes the components that will be exposed as Web Services' endpoints; these are called the port-component(s). A set of port-components defines a webservice-description, and a webservice-description uses a WSDL Definition file for a complete description of the Web Services' endpoints.

Each port-component is linked to the J2EE component that will respond to the request (service-impl-bean with a servlet-link or ejb-link child element) and to a WSDL port (wsdl-port defining the port's QName). A list of JAX-RPC Handlers is provided for each port-component. The optional service-endpoint-interface defines the methods of the J2EE components that will be exposed (no inheritance needed).

A JAX-RPC Handler is a class used to read and/or modify the SOAP Message before transmission and/or after reception (refer to the JAX-RPC v1.1 spec. chap#12 "SOAP Message Handlers").The Session Handler is a simple example that will read/write SOAP session information in the SOAP Headers. Handlers are identified with a unique name (within the application unit), are initialized with the init-param(s), and work on processing a list of SOAP Headers defined with soap-headers child elements. The Handler is run as the SOAP actor(s) defined in the list of soap-roles.

A webservice-description defines a set of port-components, a WSDL Definition (describing the Web Service) and a mapping file (WSDL-2-Java bindings). The wsdl-file element and the jaxrpc-mapping-file element must specify a path to a file contained in the module unit (i.e., the war/jar file). Note that a URL cannot be set here. The specification also requires that the WSDLs be placed in a wsdl subdirectory (i.e., WEB-INF/wsdl or META-INF/wsdl); there is no such requirement for the jaxrpc-mapping-file. All the ports defined in the WSDL must be linked to a port-component. This is essential because the WSDL is a contract between the endpoint and a client (if the client uses a port not implemented/linked with a component, the client call will systematically fail).

As for all other Deployment Descriptors, a standard XML Schema is used to constrain the XML.

D. Simple Example (expose a JAX-RPC Endpoint) of webservices.xml

<?xml version="1.0"?>

<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"
             version="1.1">
  <display-name>Simple Web Service Endpoint DeploymentDesc</display-name>

  <webservice-description>
    <!-- name must be unique in an Application unit -->
    <!-- Should not contain spaces !!! -->
    <webservice-description-name>
      SimpleWebServiceEndpoint
    </webservice-description-name>

    <!-- Link to the WSDL file describing the endpoint -->
    <wsdl-file>WEB-INF/wsdl/warendpoint.wsdl</wsdl-file>

    <!-- Link to the mapping file describing binding between WSDL and Java -->
    <jaxrpc-mapping-file>WEB-INF/warEndpointMapping.xml</jaxrpc-mapping-file>

    <!-- The list of endpoints -->
    <port-component>

      <!-- Unique name of the port-component -->
     
<!-- Should not contain spaces !!! -->
      <port-component-name>WebappPortComp1</port-component-name>

      <!-- The QName of the WSDL Port the J2EE port-component is linked to -->
      <!-- Must Refers to a port in associated WSDL document -->
      <wsdl-port xmlns:ns="
http://wsendpoint.servlets.ws.objectweb.org">
          ns:wsendpoint1
      </wsdl-port>

      <!-- The endpoint interface defining methods exposed -->
      <!--    for the endpoint                             -->

      <service-endpoint-interface>
        org.objectweb.ws.servlets.wsendpoint.WSEndpointSei
      </service-endpoint-interface>

      <!-- Link to the J2EE component (servlet/EJB)    -->
      <!-- implementing methods of the SEI             -->

      <service-impl-bean>
        <!-- name of the servlet defining the JAX-RPC endpoint    -->
        <!-- can be ejb-link if SSB is used (only in EjbJar!)    -->
        <servlet-link>WSEndpoint</servlet-link>
      </service-impl-bean>

      <!-- The list of optional JAX-RPC Handlers -->
      <handler>
        <handler-name>MyHandler</handler-name>
        <handler-class>org.objectweb.ws.handlers.SimpleHandler</handler-class>

        <!-- A list of init-param for Handler configuration -->
        <init-param>
           <param-name>param1</param-name>
           <param-value>value1</param-value>
        </init-param>
        <init-param>
           <param-name>param2</param-name>
           <param-value>value2</param-value>
        </init-param>
      </handler>
    </port-component>
  </webservice-description>
</webservices>

E. The optional jonas-webservices.xml

The jonas-webservices.xml file is an optional deployment descriptor. This descriptor is used by WsGen to set some specifics for the generated webapp that is in charge of the SOAP request dispatching. Its role is to allow for the specifications of the webapp's name, context root, security settings and endpoint URL customization.

Some parameters are only used if the web service is implemented by a Session Bean:
War Name: Specifies the name of the generated WAR. Setting the <war> element is optional; if it is not specified, then the default naming convention is used to retrieve the WAR name from the ejbjar's name.

   Default Naming: <ejbjar-name>.jar will have an <ejbjar-name>.war WebApp.

Context Root: Specifies the context root of the generated WAR. Setting the <context-root> element is optional; if it is not specified, then the default naming convention is used and the context root will be the same as the WAR's name.

   Default Naming: <webapp-name>.war will have a <webapp-name> context root.

Endpoint URL Customization: Specifies the endpoint URL of a given jonas-port-component. Setting the <endpoint-url> element is optional; if it is not specified, then the default naming convention is used and the URL will look like /<context-root>/<port-component-name>/<wsdl:port-name>.

Security: The security settings specify which security settings, if any, the generated webapp should use. Setting up security within this file is very similar to how security would be set up in a regular web.xml.

NOTE: When using the <endpoint-security-constraint>, <endpoint-login-config>, or <endpoint-security-role> elements, the j2ee namespace must be included in the jonas-webservices element (that is, xmlsn:j2ee="http://java.sun.com/xml/j2ee"), and the namespace for all elements within these tags (that is, the 'j2ee' in the example below) must be specified.

   Security Constraint: the <endpoint-security-constraint> specifies the <security-constraint> in the web.xml of the generated webapp.

   Login Config: the <endpoint-login-config> specifies the <login-config> in the web.xml of the generated webapp.

   Security Role: the <endpoint-security-role> specifies the <security-role> in the web.xml of the generated webapp.

   Realm: the <endpoint-realm> specifies the security realm for the generated webapp.

   Realm Name: the <endpoint-realm-name> specifies the name of the security realm for the generated webapp.

Example:
<?xml version="1.0"?>
<jonas-webservices xmlns="http://www.objectweb.org/jonas/ns"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:j2ee:"http://java.sun.com/xml/ns/j2ee"
                   xsi:schemaLocation="http://www.objectweb.org/jonas/ns http://www.objectweb.org/jonas/ns/jonas_j2ee_web_services_4_5.xsd">

  <!-- the name of the webapp in the EAR              -->
  <!-- (it is the same as the one in application.xml) -->
  <war>dispatchingWebApp.war</war>

  <!-- the context root the webapp should use -->
  <context-root>endpoint</context-root>

  <jonas-port-component>
    <port-component-name>ssbEndpoint</port-component-name>
    <!-- We can specify with endpoint-uri the URL we want to have for the given port.      -->
    <!-- Will be something like : http://<host>:<port>/<context-root>/services1/webservice -->
    <endpoint-uri>/services1/webservice</endpoint-uri>
  </jonas-port-component>

  <!-- everthing in this element will appear in the security-constraint -->
  <!-- element in the web.xml of the generated webapp                   -->
  <endpoint-security-constraint>
    <j2ee:web-resouce-collection>
      <j2ee:web-resource-name>Stateless Session Bean Endpoint</j2ee:web-resource-name>
      <j2ee:url-pattern>/*</j2ee:url-pattern>
    </j2ee:web-resource-collection>
    <j2ee:auth-constraint>
      <j2ee:role-name>admin</j2ee:role-name>
    </j2ee:auth-constraint>
  </endpoint-security-constraint>

  <!-- everything in this element will appear in the login-config -->
  <!-- element in the web.xml of the generated webapp             -->
  <endpoint-login-config>
    <j2ee:auth-method>BASIC</j2ee:auth-method>
    <j2ee:realm-name>Endpoint Authentication Area</j2ee:realm-name>
  </endpoint-login-config>

  <!-- everything in this element will appear in the security-role -->
  <!-- element in the web.xml of the generated webapp              -->
  <endpoint-security-role>
    <j2ee:role-name>admin</j2ee:role-name>
  </endpoint-security-role>

  <!-- the realm the generated webapp should use -->
  <endpoint-realm>memrlm_1</endpoint-realm>

  <!-- the name of the realm the generated webapp should use -->
  <endpoint-realm-name>Endpoint Authentication Area</endpoint-realm-name>

</jonas-webservices>

F. Changes to jonas-web.xml

JOnAS allows the developer to fully configure an application by setting the hostname, the context-root, and the port used to access the Web Services. This is done in the jonas-web.xml of the dispatching WebApp.
host: configure the hostname to use in URL (must be an available web container host).
port: configure the port number to use in URL (must be an available HTTP/HTTPS connector port number).

When these values are not set, JOnAS will attempt to determine the default values for host and port.
Limitations:
- The host can only be determined when only one host is set for the web container.
- The port can only be determined when only one connector is used by the web container.

3. The client of a Web Service

An EJB or a servlet that wants to use a Web Service (as client) must declare a dependency on the Web Service with a service-ref element (same principle as for all *-ref elements).

A. The service-ref element

The service-ref element declares reference to a Web Service used by a J2EE component in the web, EJB and Client application Deployment Descriptor.
The component uses a logical name called a service-ref-name to lookup the service instance. Thus, any component that performs a lookup on a Web Service must declare a dependency (the service-ref element) in the standard deployment descriptor (web.xml, ejb-jar.xml or application-client.xml).

Example of service-ref:
  <service-ref>
    <!-- 
(Optional) A Web services description that can be used
         in administration tool.
-->
    <description>Sample WebService Client</description>

    <!--
(Optional) The WebService reference name -->
    <display-name>WebService Client 1</display-name>

    <!--
(Optional) An icon for this WebService. -->
    <icon> <!-- ... --> </icon>

    <!--
The logical name for the reference that is used in the client source
         code. It is recommended, but not required that the name begin with
         'services/'
-->
    <service-ref-name>services/myService</service-ref-name>

    <!--
Defines the class name of the JAX-RPC Service interface that
        the client depends on. In most cases, the value will be:
        javax.xml.rpc.Service but a generated specific Service Interface
        class may be specified (requires WSDL knowledge and thus
        the wsdl-file element).
-->
    <service-interface>javax.xml.rpc.Service</service-interface>

    <!--
(Optional) Contains the location (relative to the root of
         the module) of the web service WSDL description.

         - needs to be in the wsdl directory.
         - required if generated interface and sei are declared. -->
    <wsdl-file>WEB-INF/wsdl/stockQuote.wsdl</wsdl-file>
   
    <!--
(Optional) A file specifying the correlation of the WSDL definition
         to the interfaces (Service Endpoint Interface, Service Interface).

         - required if generated interface and sei (Service Endpoint
         Interface) are declared.
-->
    <jaxrpc-mapping-file>WEB-INF/myMapping.xml</jaxrpc-mapping-file>

    <!--
(Optional) Declares the specific WSDL service element that is being
         referred to. It is not specified if no wsdl-file is declared or if
         WSDL contains only 1 service element. A service-qname is composed
         of a namespaceURI and a localpart. It must be defined if more than 1
         service is declared in the WSDL.
-->
      <service-qname xmlns:ns="
http://beans.ws.objectweb.org">
         ns:MyWSDLService
    </service-qname>

    <!--
Declares a client dependency on the container for resolving a Service
         Endpoint Interface to a WSDL port. It optionally associates the
         Service Endpoint Interface with a particular port-component.
-->
    <port-component-ref>

      <service-endpoint-interface>

     org.objectweb.ws.beans.ssbendpoint.MyService
         </service-endpoint-interface>

      <!-- Defines a link to a port component declared in another unit
           of the application -->
      <!-- link is only used when an application module wants to access a  -->
      <!-- web service colocated in the same application unit             -->
      <port-component-link>ejb_module.jar#PortComponentName
</port-component-link>
    </port-component-ref>

    <!--A list of Handlers to use for this service-ref  -->
    <handler>
       <!-- 
Must be unique within the module. -->
       <handler-name>MyHandler</handler-name>

       <handler-class>org.objectweb.ws.handlers.myHandler</handler-class>

       <!-- A list of init-params (couple name/value) for Handler
            initialization -->
       <init-param>
         <param-name>param_1</param-name>
         <param-value>value_1</param-value>
       </init-param>

       <!-- A list of QNames specifying the SOAP Headers the handler
            will work on. Namespace and locapart values must be found
            inside the WSDL. -->
       <soap-header xmlns:ns="
http://ws.objectweb.org">
            ns:MyWSDLHeader
       </soap-header>

       <!-- A list of
SOAP actor definitions that the Handler will play
            as a role. A soap-role is a namespace URI.
-->
       <soap-role>http://actor.soap.objectweb.org</soap-role>

       <!-- A list of 
port-name elements that defines the WSDL port-name that
            a handler should be associated with. If no port-name is specified,
            the handler is assumed to be associated with all ports of the
            service-ref.
-->
       <port-name>myWSDLPort</port-name>
    </handler>
  </service-ref>

B. The jonas-service-ref element

A jonas-service-ref must be specified for each service-ref declared in the standard Deployment Descriptor. The jonas-service-ref adds JOnAS-specific (and Web Service engine-specific) information to service-ref elements.

Example of jonas-service-ref:
    <jonas-service-ref>

      <!-- Define the service-ref contained in the component
           deployment descriptor (web.xml, ejb-jar.xml, application-client.xml).
           used as a key to associate a service-ref to its correspondent
           jonas-service-ref-->
      <service-ref-name>services/myService</service-ref-name>

      <!-- Define the physical name of the resource. -->
      <jndi-name>webservice_1</jndi-name>
     
      <!-- A list of init-param used for specific configuration of
           the service -->
      <jonas-init-param>
        <param-name>param</param-name>
        <param-value>name</param-value>
      </jonas-init-param>
    </jonas-service-ref>

4. WsGen

WsGen is a new JOnAS tool that works in the same way as GenIC. It takes archive files (EJB-JAR, WAR, JAR client, EAR) and generates all the necessay components related to web services:

For example, to provide an EJB-exposing method as a web service, a developer creates a webservices.xml file packaged in EjbJar's META-INF directory. WsGen automatically creates a configured webapp (using an Axis servlet) and wraps it (ejbjar + webapp) in an EAR file.

With a JaxRpc class, WsGen adds a servlet (an Axis servlet) inside the existing web deployment descriptor and generates an Axis-specific configuration file.

When using service-ref (from ejbjars, web applications, or clients), WsGen automatically generates a Stub from WSDL (if a generated service interface name is provided).

Usage

WsGen is used typically from an ant build file. Simply add this taskdef under the ejbjar taskdef:

<taskdef name="wsgen" classname="org.objectweb.jonas.ant.WsGenTask"
   classpath="${jonas.root}/lib/common/ow_jonas_ant.jar" />
<wsgen srcdir="${temp.dir}"
   destdir="${dist.dir}"
   verbose="false"
   debug="false">
      <include name="webapps/wswarsample.war"/>
</wsgen>

See the $JONAS_ROOT/examples/webservices samples for complete build scripts.

Note that the ejbjar/webapp/client archive must include WSDL, jax-rpc-mappings used in service-ref, or webservices.xml. When these files are used from a service-ref, they are added into the generic ejb-jar with the ejbjar ant task of JOnAS; you must ensure that they have been placed inside the srcdir given to the ejbjar task (otherwise, the ejbjar task cannot find them and will produce an error).

This task is a directory-based task and, as such, forms an implicit Fileset. This defines which files, relative to the srcdir, will be processed. The wsgen task supports all the attributes of Fileset to refine the set of files to be included in the implicit fileset.

Attribute Description Required
srcdir Directory where file archive (EjbJar, War, Client, Ear) is located Yes
destdir Directory where generated files will be placed No
verbose Verbose mode (Defaults to false) No
debug Debug mode (Defaults to false) No
javacopts List of options given to the java compiler No
jonasroot Directory where JOnAS is installed No
jonasbase Directory where JOnAS configuration is stored No

Wsgen is also usable from the command line with WsGen script (available on *nix and Windows).