Version 2

    Providing an RPC style service endpoint

     

    You have two choices. Either you expose the web service as a java service endpoint (JSE) or as an EJB service

    endpoint using a stateless session bean. For this tutorial we'll start off providing a JSE. I use code from the

    web service samples that you can find as part of the main testsuite.

     

     

     

     

    The service endpoint interface

     

    Typically you start off with a service endpoint interface (SEI) like this

     

    public interface Organization extends Remote
    {
       String getContactInfo(String organization) throws RemoteException;
    
       Person jobRequest(Person target) throws RemoteException;
    }
    

     

    There are certain rules you have to follow for a valid SEI. For example

     

    • The SEI must extend Remote

    • All methods must include RemoteException in their throws clause

    • Method parameter types are limited to the ones specified by the JAX-RPC specification

     

    The endpoint implementation bean

     

    The SEI defines the java contract of the web service. You will also need to provide an implementation bean.

    Here it is

     

    public class OrganizationJSEEndpoint implements Organization
    {
       public String getContactInfo(String organization)
       {
          log.info("getContactInfo: " + organization);
          return "The '" + organization + "' boss is currently out of office, please call again.";
       }
    
       public Person jobRequest(Person target) 
       {
          log.info("jobRequest: " + target);
          return target;   
       }
    }
    

     

    Generating required deployment artifacts

     

    First thing on the bumpy road to a valid WS4EE deployment is to generate the required server side deployment

    artifacts. JBossWS does not have its own toolset yet. We recommend you use wscompile from the

    Java Web Service Development Pack.

     

    To describe the web service, you need a document in the web service description language (WSDL). The WSDL is

    programming language independent. Therefore we need another document that describes the mapping details between

    Java and XML, this is called jaxrpc-mapping.xml. Both can be generated with wscompile.

     

     

       wscompile -cp output/classes -gen:server -f:rpcliteral -mapping jaxrpc-mapping.xml config.xml
    

     

    wscompile needs a configuration file for its operation, we use

     

    <configuration
      xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
    
      <service name="OrganizationService"
        targetNamespace="http://org.jboss.test.webservice/samples"
        typeNamespace="http://org.jboss.test.webservice/samples/types"
        packageName="org.jboss.test.webservice.samples">
        <interface name="org.jboss.test.webservice.samples.Organization"></interface>
      </service>
    
    </configuration>
    

     

    The Web Service Description

     

    The WSDL for our SEI is shown next

     

    <definitions name="OrganizationService" targetNamespace="http://org.jboss.test.webservice/samples"
     xmlns:tns="http://org.jboss.test.webservice/samples" xmlns="http://schemas.xmlsoap.org/wsdl/" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="http://org.jboss.test.webservice/samples/types" 
     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    
      <!-- Complex type definitions -->
      <types>
        <schema targetNamespace="http://org.jboss.test.webservice/samples/types" 
         xmlns:tns="http://org.jboss.test.webservice/samples/types" 
         xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
         xmlns="http://www.w3.org/2001/XMLSchema">
          <complexType name="Person">
            <sequence>
              <element name="age" type="int"></element>
              <element name="name" type="string" nillable="true"></element>
            </sequence>
          </complexType>
        </schema>
      </types>
    
      <!-- The structure of the individual messages -->
      <message name="Organization_getContactInfo">
        <part name="String_1" type="xsd:string"></part>
      </message>
      <message name="Organization_getContactInfoResponse">
        <part name="result" type="xsd:string"></part>
      </message>
      <message name="Organization_jobRequest">
        <part name="Person_1" type="ns2:Person"></part>
      </message>
      <message name="Organization_jobRequestResponse">
        <part name="result" type="ns2:Person"></part>
      </message>
    
      <!-- What operation the service provides and what messages it exchanges -->
      <portType name="Organization">
        <operation name="getContactInfo" parameterOrder="String_1">
          <input message="tns:Organization_getContactInfo"/>
          <output message="tns:Organization_getContactInfoResponse"></output>
        </operation>
        <operation name="jobRequest" parameterOrder="Person_1">
          <input message="tns:Organization_jobRequest"/>
          <output message="tns:Organization_jobRequestResponse"></output>
        </operation>
      </portType>
    
      <!-- How the service is bound -->
      <binding name="OrganizationBinding" type="tns:Organization">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"></soap:binding>
        <operation name="getContactInfo">
          <soap:operation soapAction=""></soap:operation>
          <input>
            <soap:body use="literal" namespace="http://org.jboss.test.webservice/samples"></soap:body>
          </input>
          <output>
            <soap:body use="literal" namespace="http://org.jboss.test.webservice/samples"></soap:body>
          </output>
        </operation>
        <operation name="jobRequest">
          <soap:operation soapAction=""></soap:operation>
          <input>
            <soap:body use="literal" namespace="http://org.jboss.test.webservice/samples"></soap:body>
          </input>
          <output>
            <soap:body use="literal" namespace="http://org.jboss.test.webservice/samples"></soap:body>
          </output>
        </operation>
      </binding>
    
      <!-- Where the service is located -->
      <service name="OrganizationService">
        <port name="OrganizationPort" binding="tns:OrganizationBinding">
          <soap:address location="REPLACE_WITH_ACTUAL_URL"></soap:address>
        </port>
      </service>
    </definitions>
    

     

    Note, the exact location of the service can be left unspecified as this entry will be replaced by JBossWS

    during deploytime.

     

    Java to XML mapping

     

    As already mentioned, there is nothing Java specific in the WSDL. How XML namespaces map to

    Java packages and other mapping concerns are described in jaxrpc-mapping.xml, which is shown next

     

    <java-wsdl-mapping version="1.1" 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_jaxrpc_mapping_1_1.xsd">
    
      <package-mapping>
        <package-type>org.jboss.test.webservice.samples</package-type>
        <namespaceURI>http://org.jboss.test.webservice/samples/types</namespaceURI>
      </package-mapping>
      <package-mapping>
        <package-type>org.jboss.test.webservice.samples</package-type>
        <namespaceURI>http://org.jboss.test.webservice/samples</namespaceURI>
      </package-mapping>
    
      <java-xml-type-mapping>
        <java-type>org.jboss.test.webservice.samples.Person</java-type>
        <root-type-qname xmlns:typeNS="http://org.jboss.test.webservice/samples/types">typeNS:Person</root-type-qname>
        <qname-scope>complexType</qname-scope>
        <variable-mapping>
          <java-variable-name>age</java-variable-name>
          <xml-element-name>age</xml-element-name>
        </variable-mapping>
        <variable-mapping>
          <java-variable-name>name</java-variable-name>
          <xml-element-name>name</xml-element-name>
        </variable-mapping>
      </java-xml-type-mapping>
    
      <service-interface-mapping>
        <service-interface>org.jboss.test.webservice.samples.OrganizationService</service-interface>
        <wsdl-service-name xmlns:serviceNS="http://org.jboss.test.webservice/samples">serviceNS:OrganizationService</wsdl-service-name>
        <port-mapping>
          <port-name>OrganizationPort</port-name>
          <java-port-name>OrganizationPort</java-port-name>
        </port-mapping>
      </service-interface-mapping>
    
      <service-endpoint-interface-mapping>
        <service-endpoint-interface>org.jboss.test.webservice.samples.Organization</service-endpoint-interface>
        <wsdl-port-type xmlns:portTypeNS="http://org.jboss.test.webservice/samples">portTypeNS:Organization</wsdl-port-type>
        <wsdl-binding xmlns:bindingNS="http://org.jboss.test.webservice/samples">bindingNS:OrganizationBinding</wsdl-binding>
        <service-endpoint-method-mapping>
          <java-method-name>getContactInfo</java-method-name>
          <wsdl-operation>getContactInfo</wsdl-operation>
          <method-param-parts-mapping>
            <param-position>0</param-position>
            <param-type>java.lang.String</param-type>
            <wsdl-message-mapping>
              <wsdl-message xmlns:wsdlMsgNS="http://org.jboss.test.webservice/samples">wsdlMsgNS:Organization_getContactInfo</wsdl-message>
              <wsdl-message-part-name>String_1</wsdl-message-part-name>
              <parameter-mode>IN</parameter-mode>
            </wsdl-message-mapping>
          </method-param-parts-mapping>
          <wsdl-return-value-mapping>
            <method-return-value>java.lang.String</method-return-value>
            <wsdl-message xmlns:wsdlMsgNS="http://org.jboss.test.webservice/samples">wsdlMsgNS:Organization_getContactInfoResponse</wsdl-message>
            <wsdl-message-part-name>result</wsdl-message-part-name>
          </wsdl-return-value-mapping>
        </service-endpoint-method-mapping>
        <service-endpoint-method-mapping>
          <java-method-name>jobRequest</java-method-name>
          <wsdl-operation>jobRequest</wsdl-operation>
          <method-param-parts-mapping>
            <param-position>0</param-position>
            <param-type>org.jboss.test.webservice.samples.Person</param-type>
            <wsdl-message-mapping>
              <wsdl-message xmlns:wsdlMsgNS="http://org.jboss.test.webservice/samples">wsdlMsgNS:Organization_jobRequest</wsdl-message>
              <wsdl-message-part-name>Person_1</wsdl-message-part-name>
              <parameter-mode>IN</parameter-mode>
            </wsdl-message-mapping>
          </method-param-parts-mapping>
          <wsdl-return-value-mapping>
            <method-return-value>org.jboss.test.webservice.samples.Person</method-return-value>
            <wsdl-message xmlns:wsdlMsgNS="http://org.jboss.test.webservice/samples">wsdlMsgNS:Organization_jobRequestResponse</wsdl-message>
            <wsdl-message-part-name>result</wsdl-message-part-name>
          </wsdl-return-value-mapping>
        </service-endpoint-method-mapping>
      </service-endpoint-interface-mapping>
    </java-wsdl-mapping>
    

     

    The endpoint as a web application

     

    A java service endpoint is deployed as a web application. Therefore we need a web.xml deployment descriptor, which

    we will have to code by hand.

     

    <web-app 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://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
      version="2.4">
    
      <servlet>
        <servlet-name>Organization</servlet-name>
        <servlet-class>org.jboss.test.webservice.samples.OrganizationJSEEndpoint</servlet-class>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>Organization</servlet-name>
        <url-pattern>/Organization</url-pattern>
      </servlet-mapping>
    
    </web-app>
    

     

    Note, that we declare the endpoint implemenation bean in the <servlet-class> element, but it is actually not

    a servlet at all.

     

     

     

     

     

    The webservices deployment descriptor

     

    One more descriptor is needed that glues everything together. It is called webservices.xml, is placed in WEB-INF, and must also be coded

    by hand. Here it is

     

    <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">
    
      <webservice-description>
        <webservice-description-name>OrganizationServiceJSE</webservice-description-name>
        <wsdl-file>WEB-INF/wsdl/OrganizationService.wsdl</wsdl-file>
        <jaxrpc-mapping-file>WEB-INF/jaxrpc-mapping.xml</jaxrpc-mapping-file>
        <port-component>
          <port-component-name>PortComponent</port-component-name>
          <wsdl-port>OrganizationPort</wsdl-port>
          <service-endpoint-interface>org.jboss.test.webservice.samples.Organization</service-endpoint-interface>
          <service-impl-bean>
            <servlet-link>Organization</servlet-link>
          </service-impl-bean>
        </port-component>
      </webservice-description>
    </webservices>
    

     

    Deployment to JBoss

     

    Then we package everything together and deploy to JBoss. On the server we should see messages like this

     

    23:12:56,515 INFO  [TomcatDeployer] deploy, ctxPath=/ws4ee-samples-server-jse, warUrl=file:/.../ws4ee-samples-server-jse-exp.war/
    23:12:57,125 INFO  [WSDLFilePublisher] WSDL published to: file:/.../data/wsdl/ws4ee-samples-server-jse.war/OrganizationService.wsdl
    23:12:57,546 INFO  [AxisService] WSDD published to: ...\data\wsdl\ws4ee-samples-server-jse.war\PortComponent.wsdd
    23:12:58,328 INFO  [AxisService] Web Service deployed: http://TDDELL:8080/ws4ee-samples-server-jse/Organization
    

     

    A potential client can access the WSDL from this address

     

       http://TDDELL:8080/ws4ee-samples-server-jse/Organization?wsdl
    

     

    How to connect to this endpoint from a Java client will be shown in the next tutorial.