Client Application Developer’s Guide

     Previous  Next    Open TOC in new window    View as PDF - New Window  Get Adobe Reader - New Window
Content starts here

Invoking Data Services Through Web Services

This chapter explains how to expose data services as industry-standard Web services and how to create client applications that invoke data services through those web services.

This chapter includes these topics:

 


Overview

The ALDSP Native Web Services feature lets you map data services to web services directly. Client applications access data through web services with the Data Services Mediator API.

Tip: Invoking Data Services from Java Clients, discusses the Mediator API in detail. We recommend that you review that chapter before you develop web service-enabled applications.

When you expose data services as Web services, your information assets become accessible to a wide variety of client types, including other Java Web service clients, Microsoft ADO.NET, other non-Java applications, and other Web services. Figure 4-1 illustrates the various approaches that client application developers can take to integrating data services and Web services. Web service WSDL operations map directly to data service operations on the server.

Tip: For detailed information on creating data service operations (read, create, update, delete, libraryFunction, and libraryProcedure) see the Data Services Developer’s Guide.
Figure 4-1 Web Services Enable Access to ALDSP-Enabled Applications from a Variety of Clients

Web Services Enable Access to ALDSP-Enabled Applications from a Variety of Clients

 


Before You Begin

This chapter is intended for Java developers who wish to write client applications that invoke data services through web services.

We recommend that:

 


Getting Started

This section lists the basic steps to get started writing a Java client application that interacts with a data service.

Basic Steps

These are the basic steps to follow when developing a Java client that invokes data service functions through web service operations.

  1. The first thing you need is a data service to call. Someone (typically a data service developer) creates the data service.
  2. A Web Service Map file must then be generated from the data service. The map file is typically generated by a data service developer. The procedure for generating a Web Service Map file, see the Data Services Developer’s Guide.
  3. Deploy and test the web service.
  4. Decide whether to use the Static or Dynamic Mediator API to interact with the web service from your Java client. See Dynamic and Static Mediator APIs for a summary of each API. To use the Static Mediator API, you need to generate or obtain the Web Services Mediator Client JAR file. For instructions on generating a Web Services Mediator Client JAR, see the Data Services Developer’s Guide.
  5. Tip: The Static Mediator API is generally recommended for most use cases. The Static Mediator API is type safe and generally easier to use than the Dynamic Mediator API.
  6. Set up your Java build environment. You need certain JAR files in your CLASSPATH. See Setting the CLASSPATH for details.
  7. Learn the WSDL operations that are available to you for accessing data service functions. The operations have the same names and parameters as the data service from which they were generated.
  8. Write and test your client application. See the sample applications provided in this document: Sample Static Mediator Application and Sample Dynamic Mediator Application.

Setting the CLASSPATH

CLASSPATH settings depend on whether you are using the Static or Dynamic Mediator API.

Static Java Mediator API Client CLASSPATH

The following JARs must be in the CLASSPATH of your Java application if you are using the Static Mediator API.

Dynamic Java Mediator API Client CLASSPATH

The following JARs must be in the CLASSPATH of your Java application if you are using the Dynamic Mediator API.

Running the Sample Applications

A good way to get started is to run the sample application code that is provided in this chapter. Samples that use the Static and the Dynamic Mediator APIs are included. The samples illustrate simple but common use cases: retrieving data, modifying it, and updating it. See Sample Static Mediator Application and Sample Dynamic Mediator Application.

 


Sample Static Mediator Application

This section presents a simple Java program that you can copy, compile, and run. The program uses the Static Mediator API to invoke WSDL operations to perform the following basic tasks: authenticating the client, retrieving data, modifying data, and updating data on the server. For an overview of the Static Mediator API, see Dynamic and Static Mediator APIs.

Topics include:

Setting Up the Sample Data Service

The sample application presented here is designed to work with a sample data service. You need to create this data service and configure a sever before continuing. For detailed instructions on creating the data service that is required by this sample application, see Setting Up the Sample Data Service.

Creating a Web Service Map File

To run the example, you need to generate a Web Service Map file. You can do this easily using Data Services Studio. See the Data Services Developer’s Guide for detailed instructions.

To create the file using Data Services Studio:

  1. Right-click the data service project and select New > Web Service Map.
  2. Follow the wizard to create the map file. For this example, name the file PhysicalCUSTOMER.ws.
  3. Drag the data service file, PhysicalCUSTOMER.ds onto the Web Service Mapper editor.
  4. Save the file.
  5. Deploy and test the web service. To do this, right-click the PhysicalCUSTOMER.ds file and select Test Web Service.
Tip: You can generate a Web Services Map file using Data Services Studio, the ALDSP Console, or an Ant script. These methods are described in detail in the Data Services Developer’s Guide.

Generating the Web Services Mediator Client JAR File

The sample Java application listed later in this section requires that you first generate a Web Services Mediator Client JAR file. The classes in this JAR contain type-safe methods that call WSDL operations.

Tip: You can generate a Web Services Mediator Client JAR file using Data Services Studio, the ALDSP Console, or an Ant script. These methods are described in detail in the Data Services Developer’s Guide. For this example, we will use Data Services Studio.

To generate a Web Services Mediator Client JAR file using Data Services Studio:

  1. Generate the Web Service Map file, as discussed previously in Creating a Web Service Map File.
  2. Select File > Export.
  3. In the Select dialog, select AquaLogic Data Services Platform > Web Services Mediator Client JAR File and click Next.
  4. Complete the Web Services Mediator Client JAR File dialog as follows:
  1. Click Finish.
  2. After you generate the JAR file, you must place it in the CLASSPATH for your Java build environment. See Setting the CLASSPATH for more information.
Tip: Generated classes in the JAR file are named according to the conventions described in Naming Conventions for Generated Classes.

Setting Up the Java Project

Listing 4-1 lists the sample Java client that uses the Static Mediator API to call WSDL operations. The application simply retrieves a DataObject from a data store, modifies the object, and returns it to the data store. This example assumes you are using Data Services Studio, but you can use the IDE or build environment of your choice. For this example, we set up a Java project called MediatorWSClient.

To run the sample:

  1. Create a Java project called MediatorWSClient.
  2. Set up your Java Build Path to include the JAR files listed in Setting the CLASSPATH. To do this, select Project > Properties > Java Build Path. Be sure to add the generated Web Services Mediator Client JAR file.
  3. Create a package called com.bea.ws.sample in your Java project. To do this, right-click the Java project in the Package Explorer and select New > Package.
  4. Create a Java class called StaticWSSampleApp.java in the package. To do this, right-click the package in the Package Explorer and select New > Class.
  5. Delete the default contents of the new source file and copy the entire file listed in Listing 4-1 into the source file.
  6. Save the file. Figure 4-2 shows the completed project configuration.
  7. Figure 4-2 Completed Project Configuration


    Completed Project Configuration

Note: The imported classes PhysicalCUSTOMERDAS and PhysicalCUSTOMER are taken from the Web Services Mediator Client JAR file, which must be in the CLASSPATH.
Listing 4-1 StaticWSSampleApp.java
package com.bea.ws.sample;

import das.ws.ld.PhysicalCUSTOMERDAS;
import physicaldss.physicalcustomer.PhysicalCUSTOMER;

import com.bea.dsp.das.DASResult;
import com.bea.dsp.sdo.SDOUtil;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;

public class StaticWSSampleApp {
public static void main(String[] args) throws Exception {

// Create InitialContext for mediator
Hashtable<String, String> hash = new Hashtable<String, String>();
hash.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
hash.put(Context.SECURITY_PRINCIPAL,"weblogic");
hash.put(Context.SECURITY_CREDENTIALS,"weblogic");
Context ctx = new InitialContext(hash);

String wsdlURL =            "http://localhost:7001/MediatorTest/PhysicalCUSTOMER.ws?WSDL";

// Create DataAccessService handle with Context and dataspace name
PhysicalCUSTOMERDAS das = PhysicalCUSTOMERDAS.getInstance(ctx, wsdlURL);

// Invoke the basic 'get all customers' function
DASResult<PhysicalCUSTOMER> result = das.PhysicalCUSTOMER();

// Obtain the first PhysicalCUSTOMER DataObject
PhysicalCUSTOMER customer = result.next();

        // When finished interating through results, always call dispose().
        result.dispose();

// Enable change-tracking for that PhysicalCUSTOMER
SDOUtil.enableChanges(customer);

// Modify customer
customer.setFIRST_NAME("StaticWSMediator");
customer.setEMAIL_ADDRESS("staticwsmediator@example.com");

// Send changes back to DSP - update function takes an array
// of PhysicalCUSTOMERs
das.updatePhysicalCUSTOMER(new PhysicalCUSTOMER[] { customer });
}
}

Running and Testing the Code

To test the application, simply start the server and run the Java client as a Java application. In Data Services Studio, this is commonly done by right-clicking the Java file and selecting Run As > Java Application.

To verify that the Java client worked, re-test the data service:

  1. Open the data service in the Data Service editor.
  2. Click the Test tab (see Figure 4-3).
  3. Select an operation from the drop down menu. For this example, select the PhysicalCUSTOMER() function.
  4. Click Run (see Figure 4-3).
  5. Inspect the first row of the data table. The client application changes the first customer’s name and email address to “StaticWSMediator” and “staticwsmediator@example.com” as shown in Figure 4-3.
  6. Figure 4-3 Testing the Client


    Testing the Client

Examining the Sample Code

This section discusses the parts of the Java sample in Listing 4-1. This section examines the following components of the sample code:

Importing Packages

Note that the first two imported classes come from the generated Web Services Mediator Client JAR file.

The PhysicalCUSTOMERDAS class is the generated DataAccessService class that contains Java methods to call the WSDL operations. Method names are the same as their corresponding WSDL operations. This class contains type-safe methods that map to the actual WSDL operations. The PhysicalCUSTOMER class provides the SDO interface for manipulating DataObjects returned from the data service.

import das.ws.PhysicalCUSTOMERDAS;
import physicaldss.physicalcustomer.PhysicalCUSTOMER;

import com.bea.dsp.das.DASResult;
import com.bea.dsp.sdo.SDOUtil;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;

Obtaining a Data Access Service Handle

A DataAccessService object lets you call methods on a data service. See the Javadoc for more information on this class. For the Static Mediator API, DataAccessService (DAS) classes have a factory method named getInstance() to return the handle.

The getInstance() method requires two parameters to return the handle:

        Hashtable<String, String> hash = new Hashtable<String, String>();
hash.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
hash.put(Context.SECURITY_PRINCIPAL,"weblogic");
hash.put(Context.SECURITY_CREDENTIALS,"weblogic");
Context ctx = new InitialContext(hash);

String wsdlURL =            "http://localhost:7001/MediatorTest/PhysicalCUSTOMER.ws?WSDL";

// Create DataAccessService handle with Context and dataspace name
PhysicalCUSTOMERDAS das = PhysicalCUSTOMERDAS.getInstance(ctx, wsdlURL);

Note: Both the Static and Dynamic Mediator APIs accept either a file or a WSDL URL. For example:
Note: file:///C:/RTLApp/DataServices/RTLServices/Customer.wsdl
Note: where Customer.wsdl is the WSDL file located on the local hard drive.

Retrieving Data from the Service

The generated DataAccessService method PhysicalCUSTOMER() retrieves the result set from the data service. This method returns all customer objects from the data service. The return type is a DASResult object, which works like an iterator. For more information on this return type, see Understanding DASResult.

DASResult<PhysicalCUSTOMER> result = das.PhysicalCUSTOMER();

Obtaining a DataObject from the Result

The DASResult.next() method works very much like the Java method Iterator.next(). It returns the next PhysicalCUSTOMER, which is an SDO DataObject. SDO is a Java-based data programming model (API) and architecture for accessing and updating data. For details on SDO, see Using Service Data Objects (SDO) in the ALDSP 2.5 Concepts Guide.

PhysicalCUSTOMER customer = result.next();

Disposing the Result Object

You must call DASResult.dispose() whenever you are finished iterating through a result object. For more information on dispose(), see Disposing of DASResult Objects.

result.dispose();

Modifying the DataObject

After you obtain a DataObject, you can modify it; however, if you intend to submit these changes back to the ALDSP server, you must enable change-tracking on the DataObject before making any modifications. The SDOUtil.enableChanges() method lets you enable change-tracking for a single DataObject or an array of DataObjects. For more information on this method, see Working with Data Objects. After the customer object has change-tracking enabled, the generated setters are called to modify certain values in the customer object.

Tip: Note that the getters and setters are part of the SDO API, not the Mediator API. See Data Programming Model and Update Framework for information on SDO.

    SDOUtil.enableChanges(customer);

    customer.setFIRST_NAME("StaticWSMediator");
    customer.setEMAIL_ADDRESS("staticwsmediator@example.com");

Returning Changes to the Server

Finally, the generated DataAccessService.updatePhysicalCUSTOMER() method is called with a single parameter: an array of PhysicalCUSTOMER objects. The method calls its equivalent data service function to update the database with the newly modified row of data.

das.updatePhysicalCUSTOMER(new PhysicalCUSTOMER[] { customer });

 


Sample Dynamic Mediator Application

This section presents a simple example that you can copy, compile, and run. This example uses the Dynamic Mediator API to perform these basic tasks: authenticating the client, retrieving data, modifying data, and updating data on the server.

Setting Up and Running the Sample Code

To run this sample code, follow the basic setup instructions in Sample Static Mediator Application. The procedures for creating a sample data service, setting the CLASSPATH, and running the program are the same as the Static Mediator sample; however, when using the Dynamic Mediator API, you do not need to generate or reference the Web Services Mediator Client JAR file.

Sample Java Client Code (Dynamic Mediator API)

Listing 4-2 DynamicWSSampleApp.java
package com.bea.ws.sample;

import com.bea.dsp.das.DataAccessServiceFactory;
import com.bea.dsp.das.DataAccessService;
import com.bea.dsp.das.DASResult;
import com.bea.dsp.sdo.SDOUtil;

import commonj.sdo.DataObject;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;

public class DynamicWSSampleApp {
public static void main(String[] args) throws Exception {
// Create InitialContext for mediator
Hashtable<String, String> hash = new Hashtable<String, String>();
hash.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
hash.put(Context.SECURITY_PRINCIPAL,"weblogic");
hash.put(Context.SECURITY_CREDENTIALS,"weblogic");
Context ctx = new InitialContext(hash);

String wsdlURL =             "http://localhost:7001/MediatorTest/PhysicalCUSTOMER.ws?WSDL";

// Create DataAccessService handle with Context, dataspace
// name, and data service URI
DataAccessService das = DataAccessServiceFactory.newDataAccessService
(ctx, wsdlURL);

// Invoke the basic 'get all customers' function, which takes
// no arguments
DASResult<Object> result = das.invoke("PhysicalCUSTOMER", new Object[0]);

// Obtain the first PhysicalCUSTOMER DataObject
DataObject customer = (DataObject) result.next();

        // When finished interating through results, always call dispose().
        result.dispose();

// Enable change-tracking for that PhysicalCUSTOMER
SDOUtil.enableChanges(customer);

// Modify customer
customer.set("FIRST_NAME", "DynamicWSMediator");
customer.set("EMAIL_ADDRESS", "dynamicwsmediator@bea.com");

das.invoke("updatePhysicalCUSTOMER", new Object[] { customer });
        result.dispose();

}
}

Examining the Sample Code

This section discusses the parts of the Java sample in Listing 4-2. This section examines the following components of the sample code:

Importing Classes

These classes are required by the sample. For detailed information on the classes, refer to the Javadoc on e-docs.

import com.bea.dsp.das.DataAccessServiceFactory;
import com.bea.dsp.das.DataAccessService;
import com.bea.dsp.das.DASResult;
import com.bea.dsp.sdo.SDOUtil;

import commonj.sdo.DataObject;

import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;

Obtaining a DataAccessService Handle

A DataAccessService object lets you call methods on and submit changes to a data service. The DataAccessServiceFactory requires two parameters to return the handle.

        Hashtable<String, String> hash = new Hashtable<String, String>();
hash.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
hash.put(Context.SECURITY_PRINCIPAL,"weblogic");
hash.put(Context.SECURITY_CREDENTIALS,"weblogic");
Context ctx = new InitialContext(hash);

String wsdlURL =             "http://localhost:7001/MediatorTest/PhysicalCUSTOMER.ws?WSDL";

// Create DataAccessService handle with Context, dataspace
// name, and data service URI
DataAccessService das = DataAccessServiceFactory.newDataAccessService
(ctx, wsdlURL);

Note: Both the Static and Dynamic Mediator APIs accept either a file or a WSDL URL. For example:
Note: file:///C:/RTLApp/DataServices/RTLServices/Customer.wsdl
Note: where Customer.wsdl is the WSDL file located on the local hard drive.

Retrieving Data from the Service

In this example, the invoke() method calls the WSDL operation PhysicalCUSTOMER. This method returns all customer objects from the data service. The method returns a DASResult object, which works like an iterator. For more information on this return type, see Understanding DASResult. Note that the PhysicalCUSTOMER operation takes no arguments. This signature corresponds to the data service function that the WSDL operation calls.

DASResult<Object> result = das.invoke("PhysicalCUSTOMER", new Object[0])

Obtaining a DataObject from the Result

The DASResult.next() method works very much like the Java method Iterator.next(). It returns the next object in the result set. Because the PhysicalCUSTOMER data service method returns SDO-compliant DataObjects, you can cast the return value to DataObject. SDO is a Java-based data programming model (API) and architecture for accessing and updating data. For details on SDO, see Using Service Data Objects (SDO) in the ALDSP Concepts Guide. See also What is SDO?.

    DataObject customer = (DataObject) result.next();

Disposing the Result Object

You must call DASResult.dispose() whenever you are finished iterating through a result object. For more information on dispose(), see Disposing of DASResult Objects.

    result.dispose();

Modifying the DataObject

After you obtain a DataObject, you can modify it; however, if you intend to submit these changes back to the ALDSP server, you must enable change-tracking on the DataObject before making any modifications. The SDOUtil.enableChanges() method lets you enable change-tracking for a single DataObject or an array of DataObjects. For more information on this method, see Working with Data Objects. After the customer object has change-tracking enabled, the set method is called to modify certain values in the customer object.

    // Enable change-tracking for that PhysicalCUSTOMER
    SDOUtil.enableChanges(customer);

    // Modify customer
    customer.set("FIRST_NAME", "DynamicWSMediator");
    customer.set("EMAIL_ADDRESS", "dynamicwsmediator@bea.com");

Returning Changes to the Server

Finally, the DataAccessService method invoke() is called with the update WSDL operation. The operation takes a single parameter: an array of PhysicalCUSTOMER objects. The data service function updates the database with the newly modified row of data.

das.invoke("updatePhysicalCUSTOMER", new Object[] { customer });

 


Transaction Behavior and Web Services

Transactions are not propagated from the client to the server through web services, because there is no way for a client transaction to be sent through the web services interface. If a failure occurs and there is a transaction on the client side, the transaction will be rolled back, depending on how the client handles the failure; however, the transaction is not propagated to the server.

You can configure how transactions are handled on the server by setting attributes on the static com.bea.dsp.RequestConfig.ReadTransactionMode object:

A third attribute, NOT_SUPPORTED, is not supported for web service operations. For a detailed discussion of transaction behavior with the Mediator API, see Understanding Transaction Behavior.

Listing 4-3 shows how to set the com.bea.dsp.RequestConfig.ReadTransactionMode attribute.

Listing 4-3 Setting the ReadTransactionMode Attribute
RequestConfig config = new com.bea.dsp.RequestConfig();
RequestConfig requestConfig = request.getConfig();

if(readTransactionRequired) {
    config.setEnumAttribute(RequestConfig.ReadTransactionMode.REQUIRED);
}

 


Securing Your Web Services Application

ALDSP Native Web Services supports the following security features:

Tip: For detailed information on configuring these security options, see “ Configure Security for Web Services Applications” in the Data Services Developer’s Guide.

Typically, security configuration is performed on the server side by an administrator or data services developer. As a client developer, you need to pass the required values to the server to satisfy the required authentication. See Listing 4-4 for one example.

Note: The Native Web Services feature supports only the HTTP and HTTPS transport protocols. If you wish to use another transport protocol, you must use ALDSP's AquaLogic Service Bus transport. This transport allows ALDSP data services to be exposed through ALSB.

If basic authentication is enabled, you must pass the following properties through the Mediator API using the context object. For more information on WebLogic JNDI context objects, see Programming WebLogic JNDI on e-docs.

Listing 4-4 illustrates one possible way to set up a web service security for a data access service. In this case, a client-side BinarySecurityToken credential provider is created that uses the public key infrastructure standard X.509 for identity. The credential provider is then set as a property in the Context object, which is used to create the data access service. The credential provider, security token, username token, and trust manager are standard web service security properties.

For more information refer to the WebLogic Service documentation on web services security. See also see “Configure Security for Web Services Applications” in the Data Services Developer’s Guide.

Listing 4-4 Example X.509 Certificate Token Profile Setup
Hashtable h = new Hashtable();
h.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");

// Create emtpy list of credential providers.
List credProviders = new ArrayList();

// Create a client-side BinarySecurityToken credential provider that uses
// X.509 for identity, based on certificate and keys parameters.
CredentialProvider cp = new ClientBSTCredentialProvider(cert, key);
credProviders.add(cp);

String userid = "weblogic";
String password = "weblogic";
// Create a client-side UsernameToken credential provider based on username
// and password parameters.
cp = new ClientUNTCredentialProvider(userid.getBytes(), password.getBytes());
credProviders.add(cp);

h.put(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
h.put(WSSecurityContext.TRUST_MANAGER, userTrustMgrImpl);

Context context = new InitialContext(h);


  Back to Top       Previous  Next