The following tutorial demonstrates how to access web services using the Java API for XML Web Services (JAX-WS).
Before you begin, you will need the JAX-WS tools available from Sun. If you do not have this package installed on your system, you must download the JAX-WS tools and install them. To download the JAX-WS tools, visit http://java.sun.com/webservices/. Click the link for JAX-WS. This should take you to the Java API for XML Web Services page. Click the Download Now link. After you have downloaded the software package, install it on your system.
This example was developed with JAX-WS 2.1.3 for Windows.
SQL Anywhere SOAP web services that are accessed from JAX-WS should be declared to be of format CONCRETE.
At a command prompt, run the following command to start a personal web server. Replace samples-dir with the actual location of the sample database. The -xs http(port=80)
option tells the database server to accept HTTP requests on port 80. If you already have a web server running on port 80,
use another port number such as 8080 for this tutorial and use 8080 instead of 80 in all port references.
dbeng11 -xs http(port=80) samples-dir\demo.db |
Start Interactive SQL and connect to the SQL Anywhere sample database as the DBA. Execute the following statements:
Define a stored procedure that lists some columns of the Employees table.
CREATE PROCEDURE ListEmployees() RESULT ( EmployeeID INTEGER, Surname CHAR(20), GivenName CHAR(20), StartDate DATE, TerminationDate DATE ) BEGIN SELECT EmployeeID, Surname, GivenName, StartDate, TerminationDate FROM Employees; END; |
Define a SOAP service that calls this stored procedure.
CREATE SERVICE "WS/EmployeeList" TYPE 'SOAP' FORMAT 'CONCRETE' EXPLICIT OFF DATATYPE OUT AUTHORIZATION OFF SECURE OFF USER DBA AS CALL ListEmployees(); |
The EXPLICIT clause can only be used with a SOAP or DISH service of type CONCRETE. In this example, EXPLICIT OFF indicates that the corresponding DISH service should generate XML Schema that describes the generic SimpleDataset object. This option only affects the WSDL document that is generated. Later on, we will look at an example that uses EXPLICIT ON. See Tutorial: Using data types with JAX-WS.
DATATYPE OUT indicates that explicit data type information is generated in the XML result set response. If DATATYPE OFF had been specified, then all data would be typed as string. This option does not affect the WSDL document that is generated.
Because authorization has been turned off, anyone can use this service without supplying a user name and password. The commands run under user DBA. This arrangement is simple, but not secure.
Create a DISH service to act as a proxy for the SOAP service and to generate the WSDL document.
CREATE SERVICE "WSDish" TYPE 'DISH' FORMAT 'CONCRETE' GROUP "WS" AUTHORIZATION OFF SECURE OFF USER DBA; |
The SOAP and DISH service must both be format CONCRETE. Since the EmployeeList service is in the WS group, a GROUP clause is included.
Take a look at the WSDL that the DISH service automatically creates. To do so, open a web browser and browse to the following URL: http://localhost:80/demo/WSDish. The DISH service automatically generates a WSDL document that appears in the browser window.
In particular, observe the SimpleDataset object that is exposed because the format of this service is CONCRETE and EXPLICIT is OFF. In a later step, the wsimport application uses this information to generate a SOAP 1.1 client interface for this service.
<s:complexType name="SimpleDataset">
<s:sequence>
<s:element name="rowset">
<s:complexType>
<s:sequence>
<s:element name="row" minOccurs="0" maxOccurs="unbounded">
<s:complexType>
<s:sequence>
<s:any minOccurs="0" maxOccurs="unbounded" />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType> |
In this example, the Java API for XML Web Services (JAX-WS) and the Sun Java 1.6.0 JDK are installed on drive C:. Set your PATH environment variable so that it includes the JAX-WS binaries and the JDK binaries. The binaries are located in the following directories:
c:\Sun\jaxws-ri\bin c:\Sun\SDK\jdk\bin |
At a command prompt, set your CLASSPATH environment variable.
SET classpath=.;C:\Sun\jaxws-ri\lib\jaxb-api.jar ;C:\Sun\jaxws-ri\lib\jaxws-rt.jar |
The next step is to generate the interface needed to call the web service.
At the same command prompt, create a new project directory and make this directory your current directory. Execute the following command in this directory.
wsimport -keep -Xendorsed "http://localhost:80/demo/WSDish" |
The wsimport tool retrieves the WSDL document from the given URL, generates the Java files that define the interface for it, and then compiles the Java files.
The keep option tells wsimport not to delete the .java files. Without this option, these files are deleted after the corresponding .class files have been generated. Saving these files makes it easer to examine the makeup of the interface.
The Xendorsed option allows you to use the JAX-WS 2.1 API with JDK6.
Once this command completes, you should have a new subdirectory structure named localhost\demo\ws in your current directory that contains the following Java files, along with the compiled .class versions of each Java file.
EmployeeList.java EmployeeListResponse.java FaultMessage.java ObjectFactory.java package-info.java SimpleDataset.java WSDish.java WSDishSoapPort.java |
Save the following Java source code into SASoapDemo.java. Make sure that this file is located in the same directory containing the localhost subdirectory that was generated by the wsimport tool.
// SASoapDemo.java illustrates a web service client that // calls the WSDish service and prints out the data. import java.util.*; import javax.xml.ws.*; import org.w3c.dom.Element; import org.w3c.dom.Node; import localhost.demo.ws.*; public class SASoapDemo { @WebServiceRef( wsdlLocation= "http://localhost:8080/demo/WSDish" ) public static void main( String[] args ) { try { WSDish service = new WSDish(); Holder<SimpleDataset> response = new Holder<SimpleDataset>(); Holder<Integer> sqlcode = new Holder<Integer>(); WSDishSoapPort port = service.getWSDishSoap(); // This is the SOAP service call to EmployeeList port.employeeList( response, sqlcode ); localhost.demo.ws.SimpleDataset result = response.value; SimpleDataset.Rowset rowset = result.getRowset(); List<SimpleDataset.Rowset.Row> rows = rowset.getRow(); for ( int i = 0; i < rows.size(); i++ ) { SimpleDataset.Rowset.Row row = rows.get( i ); List<Object> cols = row.getAny(); System.out.println( "Number of columns=" + cols.size() ); for ( int j = 0; j < cols.size(); j++ ) { // Column data is contained as a SOAPElement Element col = (Element)cols.get(j); System.out.print(col.getLocalName() + "=" ); Node node = col.getFirstChild(); if( node == null ) { System.out.println( "(null)" ); } else { System.out.println( node.getNodeValue() ); } } System.out.println(); } } catch (Exception x) { x.printStackTrace(); } } } |
If you chose to start the web server using a different port number such as 8080, then you will have to alter the import localhost
source line to something like the following:
import localhost._8080.demo.ws.*; |
Compile SASoapDemo.java.
javac SASoapDemo.java |
Run the compiled class file.
java SASoapDemo |
When the application sends its request to the web server, it receives an XML result set response that consists of an EmployeeListResult with a rowset containing several row entries. Also included in the response is the sqlcode result from executing the query. An example of the response is shown next.
<tns:EmployeeListResponse> <tns:EmployeeListResult xsi:type='tns:SimpleDataset'> <tns:rowset> <tns:row>...</tns:row> . . . <tns:row>...</tns:row> </tns:rowset> </tns:EmployeeListResult> <tns:sqlcode>0</tns:sqlcode> </tns:EmployeeListResponse> |
Each row in the rowset is sent in a format similar to the following.
<tns:row> <tns:EmployeeID xsi:type="xsd:int">1751</tns:EmployeeID> <tns:Surname xsi:type="xsd:string">Ahmed</tns:Surname> <tns:GivenName xsi:type="xsd:string">Alex</tns:GivenName> <tns:StartDate xsi:type="xsd:date">1994-07-12-04:00</tns:StartDate> <tns:TerminationDate xsi:type="xsd:date">2008-04-18-04:00 </tns:TerminationDate> </tns:row> |
Note that the column name and data type are included.
You can observe the response shown above through the use of proxy software that logs the XML message traffic. The proxy inserts itself between your client application and the web server.
The EmployeeList result set is displayed as (type)column name=value pairs by the SASoapDemo application. Several lines of output similar to the following should be generated.
The EmployeeList result set is displayed as column name=value pairs. Several lines of output similar to the following should be generated.
Number of columns=4 EmployeeID=102 Surname=Whitney GivenName=Fran StartDate=1984-08-28-04:00 Number of columns=4 EmployeeID=105 Surname=Cobb GivenName=Matthew StartDate=1985-01-01-05:00 . . . Number of columns=4 EmployeeID=1740 Surname=Nielsen GivenName=Robert StartDate=1994-06-24-04:00 Number of columns=5 EmployeeID=1751 Surname=Ahmed GivenName=Alex StartDate=1994-07-12-04:00 TerminationDate=2008-04-18-04:00 |
Note that the TerminationDate column is only sent when its value is not NULL. For this example, the last row in the Employees table was altered such that a non-NULL termination date was set.
Also note that date values include an offset from UTC time. In the above sample data, the server is located in the North American Eastern time zone. This is 5 hours earlier than UTC time (-05:00) for dates when daylight savings is not in effect and 4 hours earlier than UTC time (-04:00) for dates when daylight savings is in effect.
Discuss this page in DocCommentXchange. Send feedback about this page using email. |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |