7 Using the Java Smart Client

This chapter explains how to use the Java Smart Client for integration. An example is included with Oracle RTD installation.

For full information about the Java Smart Client API, see the Decision Studio online help.

This chapter contains the following topics:

7.1 Before You Begin

You must perform the following tasks first before you can work with the Java Smart Client example:

  1. Install a Java Development Kit (JDK), with the JAVA_HOME environment variable set to its location. To obtain a JDK, go to the site:

    http://developers.sun.com/downloads

    For more details about supported versions, see the documents referenced in Section 6.4, "System Requirements and Certification."

  2. Install the Oracle RTD files and deploy Oracle RTD to an application server. See Oracle Fusion Middleware Installation Guide for Oracle Business Intelligence for full information.

  3. The Java Smart Client example works with the sample CrossSell Inline Service. Because of this, you must first populate the Oracle RTD Database with the CrossSell example data, then deploy the CrossSell Inline Service using Decision Studio. For details, see the section "Populating the CrossSell Example Data" in Oracle Fusion Middleware Administrator's Guide for Oracle Real-Time Decisions and Part III, "Decision Studio Reference" for information about deploying Inline Services.

  4. Start Real-Time Decision Server. For more information, see Oracle Fusion Middleware Administrator's Guide for Oracle Real-Time Decisions.

7.2 Integrating with an Inline Service Using the Java Smart Client

In general, integration using the Java Smart Client includes the following steps:

  1. Prepare a properties file.

  2. Create a connection to the Inline Service.

  3. Create a request that identifies the Integration Point to connect to and the parameters to identify the session and any other information the Integration Point needs to determine an outcome.

  4. Invoke the request.

  5. Gather and parse any response information from Advisors.

  6. Close the connection.

This section contains the following topics:

7.2.1 Preparing the Java Smart Client Example

Note:

In Release 11g, a client request must be authenticated. This means, at a minimum, that a set of credentials must be provided on the call. By default, the policy will be username password with message level encryption. Users only need to provide a username and password, they do not have to explicitly request message level encryption.

For this example, the CrossSell Inline Service has been integrated to a simple command-line application to demonstrate how to use the Java Smart Client for integration.

You can find the source code for this example in the following file:

RTD_HOME\client\Client Examples\Java Client Example\src\com\sigmadynamics\
client\example\Example.java

Before you start, edit Example.java to include your real user name and password in the second parameter of both property setup statements:

props.put("username", "your name");
props.put("password", "your password");

To prepare the Smart Client example:

  1. Open Decision Studio and choose File > Import, then select Existing Projects into Workspace and click Next.

  2. For Select root directory, browse to RTD_HOME\client\Client Examples\Java Client Example and click OK. Then, click Finish.

  3. From the menu bar, select Window > Open Perspective > Java. If the Console view is not visible, select Window > Show View > Console.

  4. From the menu bar, select Run > Run.

  5. In the Create, manage, and run configurations screen, select Java Application and click New.

  6. Click Browse next to the Project field, then select JavaSmartClientExample and click OK.

  7. Click Search next to the Main class field, then select Example and click OK.

  8. Click Apply, then click Run. In the Console view, the following text appears:

    Ring! Ring! New telephone call!
    Enter a customer ID between 1 and 1000:
    
  9. Place the cursor after the colon, then enter a customer ID (such as 5) and press Enter. The response appears similar to the following:

    Here are the deals we've got for you:
     1: ElectronicPayments
      Electronic payments eliminate the complications of handling checks.
    Enter the line number of the offer that catches your interest, or zero if none do:
    
  10. Place the cursor after the final colon, then enter 1 to select the offer. The server responds with a final message.

  11. The process repeats. Enter a customer ID greater than 1000 to stop the program.

7.2.2 Creating the Java Smart Client Properties File

When a client application creates a Java Smart Client, it passes a set of properties to a Java Smart Client factory that represents the component's endpoint configuration. This file contains just enough information to allow the client to connect to a server endpoint. There are additional factory methods that use default configuration values; however it is best to explicitly specify the properties. The default properties file is shown in the following procedure.

The factory method uses the properties to connect to the server. When the factory connects to the server, it downloads the more complete configuration information to the client, such as the set of default responses that the client should use if it ever needs to run when the server is unavailable. The detailed client configuration is saved in a local file, the Java Smart Client configuration cache, and is updated automatically whenever the server's configuration changes.

There are two sample properties files available to edit, sdclient.properties and sdjrfclient.properties. The latter is for users who will be using the JRF web service client stack.

To create the properties file:

  1. Locate the appropriate file, sdclient.properties or sdjrfclient.properties, in RTD_HOME\client\Client Examples\Java Client Example\lib\, and open it for editing.

    As released, sdclient.properties appears as follows:

    UseEndpointsInOrder = HTTP1
    appsCacheDirectory = ${rootDir}/etc
    timeout = 0
    HTTP1.type = http
    HTTP1.url = http://localhost:8080/
    

    As released, sdjrfclient.properties appears as follows:

    clientEndPointClass=com.sigmadynamics.client.jws.JwsClientEndPoint
    UseEndpointsInOrder = HTTP1
    appsCacheDirectory = ${rootDir}/etc
    timeout = 0
    HTTP1.type = http
    HTTP1.url = http://localhost:8081/
    
  2. Modify the contents to match your server configuration. Explanations of the elements of this file are listed in Table 7-1. In particular, make sure that you have a valid cache directory and the endpoint URL is the URL and port of your local Real-Time Decision Server.

Table 7-1 Elements of sdclient.properties and sdjrfclient.properties Files

Element Description

UseEndpointsInOrder

A comma-separated list of endpoint names, indicating the order in which the endpoints should be tried when establishing an initial connection to the server cluster during the Smart Client's initialization. After initialization, the server will supply an updated list of endpoints.

The endpoint names in this list refer to definitions within this properties file; the names are not used elsewhere.

appsCacheDirectory

A file URL identifying a writable directory into which the client component may save the configuration information that it gets from the server. The cache provides insurance against the possibility that Real-Time Decision Server might be unavailable to the client application when the application initializes its client components. If sdclient.properties or sdjrfclient.properties specifies a cache directory, it must already exist, otherwise, the client will use the Java virtual machine's temp directory

timeout

The timeout, in milliseconds, used by the original attempt to contact the server during the client component's initialization. After connecting to the server, the client uses the server's timeout, configured through the JMX MBean property IntegrationPointGuaranteedRequestTimeout.

endpoint_name.type

The named endpoint type. Only HTTP is supported at this time.

endpointName.url

A URL specifying the HTTP host and port of the server's HTTP endpoint.

username

User name to connect to the server.

password

Password to connect to the server.


7.2.3 Creating the Java Smart Client

To create the Java Smart Client, open the source file for the Example application at the following location:

RTD_HOME\client\Client Examples\Java Client Example\src\com\sigmadynamics\
client\example\Example.java

Tip:

This example source code can be used as a template for your Java Smart Client implementation.

The following imports are used to support Oracle RTD integration:

import com.sigmadynamics.client.IntegrationPointRequestInterface;
import com.sigmadynamics.client.IntegrationPointResponseInterface;
import com.sigmadynamics.client.SDClientException;
import com.sigmadynamics.client.SDClientFactory;
import com.sigmadynamics.client.SDClientInterface;

In the main method, the Example application demonstrates several techniques for using SDClientFactory to create an implementation of SDClientInterface, based on the arguments supplied to the Example application.

These arguments are passed to getClient, where the proper factory method is identified.

SDClientInterface client = getClient(args);

There are several factory methods used in the process of creating a Java Smart Client. By examining getClient, we can see the various methods, as in the following annotated code:

private static SDClientInterface getClient(String[] args) {
  try {
        Properties props = null;
        if (args.length == 0) {
            //The default properties file is referenced.
            props = getDefaultHttpAddressProperties();
        }
 
        if ("-h".equals(args[0])) {
            if (args.length < 2) 
  //This prepares property with the default HTTP address of http://localhost:8080.      //This is the default installation URL and port of Real-Time Decision Server.   //Uses createHttp(java.lang.String, int, boolean).
                props = getDefaultHttpAddressProperties();
            else
  //This prepares property with a supplied HTTP address. 
  //This is the address and port of your Real-Time Decision Server,
  // if it is not at the default address. Uses createHttp(String).
                props = getHttpAddressProperties(args[1]);
        }

        if ("-u".equals(args[0])) {
            if (args.length < 2) {
                System.out.println("Missing properties file URL argument");
                System.exit(-1);
            }
  //This prepares property with the information supplied in the properties file at   //the address specified. Uses createFromProperties.
            props = getPropertiesFromURL(args[1]);
        }

        if ("-f".equals(args[0])) {
            if (args.length < 2) {
                System.out.println("Missing properties filename argument");
                System.exit(-1);
            }
  //This prepares property with the information supplied in the properties file.   //Uses createFromPropertiesURL.
            props = getPropertiesFromFileName(args[1]);
        }

        //This sets username and password for RTD Decision service security.
        props.put("username", "your name");
        props.put("password", "your password");

        // This creates RTD Client based on configuration properties.
        return SDClientFactory.createFromProperties(props);

  } catch (SDClientException e) {
        e.printStackTrace();
  }
  System.out.println("Unrecognized argument");
  System.exit(-1);
  return null;
}

These methods are summarized in the Java Smart Client API section of the Decision Studio online help.

7.2.4 Creating the Request

After populating the request, the client application calls the invoke method of SDClientInterface to send the request to the server and receives an IntegrationPointResponseInterface representing an array of choices calculated by the server.

IntegrationPointResponseInterface invoke(IntegrationPointRequestInterface request);

In the example application, this call is made:

client.invoke(request);

Note:

If the client application wants to send a request for which it does not expect a response, and for which message delivery sequence is not critical, it can use the invokeAsync method instead of invoke.

Requests sent through invokeAsync are not guaranteed to arrive at the server before requests sent through subsequent invokeAsync or invoke calls. When message delivery sequence is important, the invoke method should be used instead of invokeAsync, even when no response is expected.

After the request to the CallStart Integration Point is invoked, a new request is prepared and invoked for CallInfo.

// Supply some additional information about the telephone call.
// Apparently the CrossSell service expects very little here -- 
// just the channel again, which it already knows. Hence this message 
// could be left out with no consequences.
request = client.createRequest(INLINE_SERVICE_NAME, "CallInfo");
request.setSessionKey( SESSION_KEY, sCustID );
request.setArg( "channel", "Call");
client.invoke(request);

7.2.5 Examining the Response

When an Advisor is invoked, a number response items, also known as Choices, will be returned. Your application must be prepared to handle this number of response items. See Section 6.2.3, "Determining the Response of an Advisor" for more information.

In the client application, the selected Choices are accessible through the IntegrationPointResponseInterface returned by the invoke method. The IntegrationPointResponseInterface provides access to an array of response item objects, ResponseItemInterface, where each response item corresponds to a Choice object selected by the Advisor's Decision.

The package com.sigmadynamics.client surfaces a Choice as a collection of value strings, keyed by name string.

In our example, when invoking a request on an Advisor Integration Point, be prepared to receive a response.

// Based on what the server knows about this customer, ask for some
// product recommendations.
request = client.createRequest(INLINE_SERVICE_NAME, "OfferRequest");
IntegrationPointResponseInterface response = client.invoke(request);
request.setSessionKey( SESSION_KEY, sCustID );

Knowing the number of responses expected allows you handle them accurately. The responses are read from the array and displayed to the customer.

if ( response.size() > 0 ){
// Since I know that CrossSell's OfferDecision returns only 
// one Choice, I could get that choice from the response with
// response.get(0); Instead, I'll pretend that
// multiple offers could be returned instead of just one.
    System.out.println();
    System.out.println("Here are the deals we've got for you:");
    ResponseItemInterface[] items = response.getResponseItems();
    for ( int i = 0; i < items.length; i++ ){
      System.out.println(" " + (i+1) + ": " + items[i].getId());
      String message = items[i].getValue("message");
      if ( message != null )
        System.out.println("   " + message );
    }
    System.out.println();
    System.out.println("Enter the line number of the offer that catches your 
    interest, or zero if none do: " );

7.2.6 Closing the Loop

Many Inline Services are designed to be self learning. In the CrossSell Inline Service, the OfferResponse Informant reports interest in a cross sell offer back to a Choice Event model.

// Tell the server the good news.
request = client.createRequest(INLINE_SERVICE_NAME, "OfferResponse");
request.setSessionKey( SESSION_KEY, sCustID );
request.setArg( "choiceName", prodName );

// "Interested" is one of the Choice Events defined for the choice group, Offers.

To identify the Choice Event model and Choices, see Section 6.2.4, "Identifying Event Responses to Oracle RTD."

request.setArg( "choiceOutcome", "Interested" );
client.invoke(request);

Finally, the session is closed by invoking the CallResolution Informant in the server, which in the CrossSell example has been designed to terminate the session.

// Close the server's session.
request = client.createRequest(INLINE_SERVICE_NAME, "CallResolution");
request.setSessionKey( SESSION_KEY, sCustID );
client.invoke(request);

7.2.7 Closing the Client

When the client application is finished using its SDClientInterface, and doesn't intend to use it again, it calls the component's close method, to release any instance-specific information.

client.close();