How to write a Document Literal Top-Down Service

Date: 19-Sep-2003

After reading this how-to document you should be able to:

  • Understand what is a JAX-RPC Web Service
  • Write a Document literal Web Service using a top down approach

Introduction

This document demonstrates how to develop an Document Literal Style Web Service for Oracle Application Server 10g using the Top-Down paradigm i.e. start with the WSDL and generate all the classes and service artifacts using the definition of types and operations in the WSDL. Web Services Description Language (WSDL) is an XML-based language used to define Web services and describe how to access them. WSDL file describes the operations (i.e. methods) exposed by the service, the parameters taken by these operations, the request and response messages associated with each operation call. WSDL also specifies the location from where the Web Service can be accessed.

Document Literal Web Services are services that process XML documents. The data exchanged in the SOAP messages between the client and the Web Service is passed in XML document. There's no formal mapping between the SOAP messages and programming languages, all it says is that the SOAP message should conform to a particular XML Schema.

The Top-Down paradigm implies that you are starting with a WSDL and will write the implementation classes after the WSDL has been processed and the necessary service classes and interfaces are generated. Once the generation process is complete the Web Service implementation class can be compiled and included into the Web Service archive (EAR file) to be deployed to OC4J.

Software Requirements

  • Oracle Application Server Containers for J2EE 10g or later. You can download the OC4J from Oracle Technology Network. 

  • JDK1.4.x or above This can be downloaded here .

  • Apache Ant v1.5 or later.

  • How To Example Source code zip.

Description

Overview of JAX-RPC Web Services

The Java API for XML-based remote procedure calls (JAX-RPC) provides standard way of building portable and interoperable SOAP based Web Services. It simplifies the process of building Web services that incorporate XML-based RPC. Read more on JAX-RPC Web Services here.

The How-To Example

This how-to explains how to create a simple Document Literal style Web Service using a WSDL file and a client to access the Web Service. The Web Service provides clients with the facility to log event messages and to retrieve these event messages. The Web Service uses various user defined types to exchange log events with the client. The definition of these types is provided as XML elements in the XML schema which is referenced from the WSDL file.

The how to uses Oracle's Web Services Assembler tool to generate the service artifacts. The Web Service assembler tool takes as input, an XML config file that describes the service. It uses the definitions in the WSDL file to generate service artifacts like types, interfaces, tie and stub classes, compiles all the classes and produces an Enterprise Archive file that can be deployed to an application server to run the Web Service.

Here is the WSDL file that will be used to generate the Web Service artifacts. Listing 1 shows the part of WSDL definition required to define the method named getEvents that takes an input parameter of user defined type and return another user defined type.

	<wsdl:types>
<xs:schema>
<Xs:import namespace="http://www.ws-i.org/LoggingFacility.xsd"
schemaLocation="LoggingFacility.xsd"/>
</Xs:schema>
</wsdl:types> <wsdl:message name="getEventsRequest">
<wsdl:part name="Document" element="log:getEventsRequestElement"/>
</wsdl:message> <wsdl:message name="getEventsResponse">
<wsdl:part name="Document" element="log:getEventsResponseElement"/>
</wsdl:message>
<wsdl:portType name="LoggingFacilityLogPortType">
<wsdl:portType name="LoggingFacilityLogPortType"> <wsdl:operation name="getEvents">
<wsdl:documentation>Retrieve entries from the system log with the specified userId.</wsdl:documentation>
<wsdl:input message="tns:getEventsRequest"/>
<wsdl:output message="tns:getEventsResponse"/>
<wsdl:fault name="RepositoryMissingFault" message="tns:getEventsRepositoryMissingFault"/>
</wsdl:operation>
</wsdl:portType> <wsdl:binding name="LoggingFacilitySoapBinding" type="tns:LoggingFacilityLogPortType">
<wsdl:documentation>
<wsi:Claim conformsTo="http://ws-i.org/profiles/basic1.0/" />
</wsdl:documentation>
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<wsdl:operation name="getEvents">
<soap:operation soapAction=""/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="RepositoryMissingFault">
<soap:fault name="RepositoryMissingFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>

Listing 1

The definition of types provided in XML schema. Listing 2 shows a part of LoggingFacility.xsd schema used by the Web Service. View complete Schema definition here.

<xs:element name="getEventsRequestElement" type="log:getEventsRequestType"/>
<xs:complexType name="getEventsRequestType">
<xs:sequence>
<xs:element name="DemoUserID" type="xs:string"/>
</xs:sequence>
</xs:complexType>

<xs:element name="getEventsResponseElement" type="log:getEventsResponseType"/>
<xs:complexType name="getEventsResponseType">
<xs:sequence>
<xs:element name="LogEntry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Timestamp" type="xs:dateTime"/>
<xs:element name="ServiceID" type="xs:string"/>
<xs:element name="EventID" type="xs:string"/>
<xs:element name="EventDescription" type="xs:string"/>
<xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>

 Listing 2

Listing 3 shows the part of Web Service implementation class, that defines getEvents method.

public class DocLitLoggerImpl implements LoggingFacilityLogPortType{
   // variable to store logged events
private Set m_logSet; public DocLitLoggerImpl(){ // initialize HashSet object
m_logSet = new HashSet();
} public GetEventsResponseType getEvents(GetEventsRequestType document) throws
GetEventsFaultType_Exception, RemoteException { // create an object of GetEventsResponseType user defined type
GetEventsResponseType response = new GetEventsResponseType(); //initialize an ArrayList to store events
List responseList = new ArrayList(); // get an iterator on HashSet that stores logged events
Iterator it = m_logSet.iterator(); // get the User Id from input parameter
String id = document.getDemoUserID(); // iterate through all the logged events
while(it.hasNext()){
// get the next event
LogEventRequestType req = (LogEventRequestType)it.next(); // if User id of event is equal to input User id
if(id.equals(req.getDemoUserID())){ // create a LogEntry and add to ArrayList
responseList.add(createLogEntryFromRequest(req));
}
}
private LogEntry createLogEntryFromRequest(LogEventRequestType req) { // create a LogEntry object from the input parameter
LogEntry le = new LogEntry();
le.set_any(req.get_any());
le.setEventDescription(req.getEventDescription());
le.setEventID(req.getEventID());
le.setServiceID(req.getServiceID());
le.setTimestamp(Calendar.getInstance());
return le;
}

Listing 3

The class implements the LoggingFacilityLogPortType interface that declares the methods exposed by the Web Service. The method getEvents takes input parameter of user defined type GetEventRequestType and returns object of GetEventResponseType type . The method iterates through the HashSet object that stores all the log entries and returns the entries of specified User Id in GetEventResponseType object. The user defined type classes like GetEventResponseType, GetEventRequestType, LogEntry, the interface LoggingFacilityLogPortType and other similar artifacts are generated by the Web Services Assembler tool using the information provided in the WSDL.

The complete Web Service code can be seen here.

Listing 4 shows the part of client code that calls the getEvents() method of the Web Service.

private void runDemo() throws Exception{
  // load service using the Service URL
DocLitLogger service = (DocLitLogger)m_factory.loadService(new URL(m_serviceURL),
DocLitLogger.class, null);
// get a handle to remote service
LoggingFacilityLogPortType port = service.getDocLitLoggerPort();
((Stub)port)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY,m_serviceURL); //call method to invoke Web Service method to log events
demoLogEvents(port); //call method to invoke Web Service method to retrieve logged events
demoGetEvents(port);

}

private void demoGetEvents(LoggingFacilityLogPortType port) throws Exception {
System.out.println("Here are the events you logged in this session"); // call Web Service method to get the logged events
GetEventsResponseType resp = port.getEvents(new GetEventsRequestType(USERID)); // create LogEntry type array from Web Service return types
LogEntry entry[] = resp.getLogEntry(); // iterate through LogEntry array and display the event messages
for(int i = 0; i < entry.length; i++){
System.out.println("-------- Entry " + (i+1) + " --------");
System.out.println("Service ID= " + entry[i].getServiceID());
System.out.println("Event ID= " + entry[i].getEventID());
System.out.println("Event Description= " + entry[i].getEventDescription());
System.out.println("Event Date & TIme= " + entry[i].getTimestamp().getTime().toString());
System.out.println("------------------------------------------");
System.out.println();
}
}

Listing 4

The complete client code can be seen here.

Preparing and Running the Example

Extract the doc-lit.zip file. This will create doc-lit directory containing documentation and source code of the how-to.

In the following steps <OC4J> refers to directory where OC4J is installed.

Step a:

Start OC4J from <OC4J>/j2ee/home directory on a command promt as follows:

java -jar oc4j.jar

Step b:

Navigate to doc-lit, the sample home directory on new command window . Include ANT_HOME/bin in the PATH environment variable. Set the following properties required by the ant build script

  • Set the ORACLE_HOME environment variable to your <OC4J> root directory.
    Example:

    Windows : set ORACLE_HOME=c:\oc4j10g
    Unix    : export ORACLE_HOME=/home/oc4j10g 
  • Set the J2EE_HOME environment variable to your <OC4J>/j2ee/home directory.
    Example:

    Windows : set J2EE_HOME=c:\oc4j10g\j2ee\home
    UNIX    : export J2EE_HOME=/home/oc4j10g/j2ee/home 
  • Set the JAVA_HOME environment variable to your Java installation directory.
    Example:

    Windows : set JAVA_HOME=c:\j2sdk1.4
    UNIX    : export JAVA_HOME=/home/j2sdk1.4
Quick Start

Once you have the server configured and running, execute the following command from the prompt in Step b:

>ant

The service artifacts and implementation class will be compiled and placed into a WAR which is then placed into an EAR.

The EAR will be deployed to OC4J. Next the stubs and client will be compiled. Finally the service will be invoked by the client and you should see the output both in the server's message output and on the stdout of the client.

Step by Step
Step 1:

Generate the service artifacts. Execute the following command:

This step will generate the service artifacts which include interfaces and Tie classes. Examine the service-config.xml file. Notice that the implementation-class-name element is filled in with the implementation class provided by the demo. This class is not compiled yet so WSA will generate the artifacts and use the class name as a place holder. Once the artifacts are generated, the implementation class will have to be compiled and WSA will have to be run again with the same config file.

To generate the service artifacts type: ant gen-service.

The source code for the service-artifacts will be placed in the doc-lit/build/src/service directory using the package name oracle.demo.topdowndoclit.service. Examine the doc-lit/config/type-mapping.xml file. This file is used to instruct WSA how to map types to package name. A namespace URI is mapped to a specific package name. Notice that this example maps its types to the package oracle.demo.topdowndoclit.types. So for service artifacts the types are generated in doc-lit/src/oracle/demo/topdowndoclit/types.

Step 2:

Update the implementation.

This step will compile the implementation classes and regenerate the EAR file that will now contain both service artifacts and the implementation class. Examine the file DocLitTopdownImpl.java under doc-lit/src/service/oracle/demo/topdowndoclit/service. Notice that the class implements LoggingFacilityLogPortType which is a service artifact and thus generated by the tool. Before the first step there were no generated files so compiling this class would have failed. Now that you have already ran the gen-service task you are ready to compile the class and update the EAR.

To update the implementation type: ant update-impl

Step 3:

Deploy the Service

The service is now ready to be deployed. Examine the doclit_topdown.ear in the build directory using WinZip or any zip file browser. It should contain a WAR file named doclit_topdown-web.war. This WAR file contains all the service artifacts, implementation classes, as well as the web deployment descriptor (web.xml) and the jaxrpc deployment descriptor (jaxrpc-ri-runtime.xml).

To deploy this ear to a running instance of oc4j type: ant deploy-demo

Step 4:

Generate the stubs (client artifacts)

This step will generate the stubs for the service. A client application uses a stub to invoke operations on a remote service. Examine the file doc-lit/config/client-config.xml. This is the configuration file that the WebServices Assembler (WSA) tool uses to generate the stubs.

To generate the stubs type: ant gen-stubs

The source for the stubs will be placed in doc-lit/build/src/client.

Step 5:

Run the demo.

You are now ready to run the client. Examine the file DocLitTopdownClient.java in doc-lit/src/client/oracle/demo/topdowndoclit/ . Notice that this class uses the stubs to set an endpoint address and to invoke methods on the remote service.

To run the client type: ant run-demo

You should see some sample output on client output screen.

To undeploy the Web Service execute the command : ant teardown-demo

Resources

Summary

This how-to document explained how write a Document literal Web Service from the WSDL using the top down approach.


E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy