Creating a Real-Time Decisions Project : Day 4

In this next posting on building an Oracle Real-Time Decisions project (part 1, part2 and part 3 are here if you've not seen them already), I'm going to look at the process of creating and populating the variables that RTD will use when building my predictive model. To recap, I'm looking to build an RTD Inline Service that will decide on the most appropriate manufacturer for a customer order, with the inputs to this model being the details on the customer, details on the order and the previous history of four potential manufacturers. This step of the process is about defining variables (or "entities") to hold details on the customer, order and manufacturers, and then creating a mechanism to populate them when the inline service is invoked.

Details on the customer and the order will come from the BPEL process that calls the RTD inline service, but details on the various manufacturers will actually be held in a database table that we'll have to read from whenever the service is invoked. Starting off first with manufacturers then, I create a table called MANUF that holds details on the four manufacturerers and metrics on their manufacturing and delivery history. I've installed the Web element of Oracle Real-Time Decisions in to Oracle Application Server 10.1.3.3.1, and so I create a JDBC connection pool, and then a managed data source using the Enterprise Manager Control Web site that maps through to the schema containing this table. I then register this new data source with RTD by following the instructions on page 69 of the Oracle RTD Installation and Administration guide, it basically involves editing four XML files which whilst a bit tricky, does work and makes my new JDBC data source visibile in the RTD Studio application.

Once you've got the JDBC data source defined and registed with RTD, the next step is to create a Data Source object within RTD Studio that points through to the JDBC data source, and then use it to import the table metadata into the application. Once you've done this, you can select the table columns that you want to make available to the application, and pick one of the columns that will be used as the lookup column.

Now I've brought in the database data source, I can now create the Manufacturer entity, which I'll map to this data source in a moment so that it auto-populates when the service is invoked. To start this process, I select "New Entity" from the RTD Studio service metadata menu, like this:

and then auto-create the entity columns (entities are like tables, they exist at the table-level in RTD applications and have one or more columns associated with them) using the "Import" option. This allows me to pick a data source, suck across the columns associated with one of the tables available through the data source, and then provide a set of default values for the entity, something that RTD requires.

The columns in this new entity are then mapped to the data source columns using the Mapping tab, and finally I press the Key button to define an entity key which is defined as an integer. The final entity looks like this:

with the mapping defined as this:

The next step is to define a session variable that will hold the values of the various manufacturers during the time the service is running. To do this, I double-click on the Session entity in the Inline Service Explorer and then use the press the "Add Attribute" button to add an attribute called Manufacturer, which is then defined as a complex attribute based on the manufacturer entity I just defined earlier.

Finally, I need to go back to the Manufacturer entity settings, click on the Mapping tab and map and use the Data Source Input Values section to map the manufacturer session entity key (which will get it's value from the BPEL process) to the entity key, so RTD will do an auto-lookup of the manufacturers details from the database when required.

So the situation I'm in now is that I've defined a data source that maps to a table containing the details and metrics on manufacturers, and then I've used this data source to build an entity which is keyed on the manufacturer ID, with the entity mapping back to the data source so it knows where to get it's data from when invoked. Then, I've defined a session variable of a type "manufacturer", which is used to hold values of manufacturer entities in memory when the service is run. One thing that I'm not sure of is how we hold details on more than one manufacturer - do we read them into the session variable serially, then feed them into the model, or do we have multiple instances of this session variable, one for each manufacturer under consideration. We'll have to wait and see.

As well as requiring details on manufacturers, the inline service I'm building also need to hold details on the customer (their name, their status, their credit limit) and details of the order (the order value, the order date and so on). These values will actually come from the BPEL process calling the inline service, and so I won't need to go through the process of defining additional data sources and using these to create the entities. Instead, I just use the inline service explorer to create the new entities, with customer being created first, and I use the "Add Attribute" and "Add Key" buttons to create the required columns, like this:

I then do the same for Orders, creating an Order entity, adding just a single key (Order ID) and two attributes, Order Value and Order Date.

Next I create two more session variables, one for Customer and one for Order, creating them using the Customer and Order entity types, and defining session keys to map to the keys used by the two entities.

When everything's set up, the session variables used in the RTD inline process look like this:

So as a process the steps are:

  1. Define relational data sources if required.
  2. Define the entity, either manually or by reference to an associated data source table.
  3. Define the key for each entity.
  4. Define a session variable attribute for each entity, with the variable type being based on the entity table definition.
  5. Define a session key for each session variable attribute, based on the key for each entity.
  6. If the associated entity is auto-mapped to a database table, provide a link between the session variable key and then entity key so an auto-lookup can take place.

OK, so we're now in a position to test everything out. To do this, I need to create an Informant, an input into the RTD process that we can then use to debug and diagnose the variable initialization process.

I first of all locate the Integration Points, then Informants node in the Inline Service Explorer, and select "New Informant".

I call the new informant "Testing" and press the "Advanced" button when naming the informant to check the "Show in Decision Center" button (the Web interface for RTD that's used for monitoring the process of RTD inline services).

On the Testing informant properties page, I press the "Select" button to pick the Manufacturer session key, which is passed as in input into the informant.

Now, that's got me thinking. In a second, I'm going to add some logic that will display some of the manufacturer attributes for the manufacturer that is referenced by the manufacturer ID input value passed to the informant. To do this, it'll do a database lookup, using the key and entity binding I created earlier. I wonder, therefore, if I should do all the customer and order details lookups in this way as well, where the inputs to the Inline Service are just the customer ID, order ID and manufacturer ID, and RTD gets all the rest of the information from the database, i.e. not from the calling BPEL process? I'll carry on for the moment, but I may have to come back and revisit this later on.

Anyway, the next step is to add some logic to this informant, logic that is going to output the diagnostic data we're looking for. To do this, I click on the Logic tab and type in the following Java code:

logInfo("Manufacturer name = " + session().getManufacturer().getName());
logInfo("Manufacturer accepted orders = " + session().getManufacturer().getNumAcceptedOrders());

like this:

Be careful with the variable names etc, they're case sensitive - in my case, RTD took the column name NUM_ACCEPTED_ORDERS and turned it into the java method getNumAcceptedOrders, which is referenced through the class session().getManufacturer().getNumAcceptedOrders - it helps with RTD if you're got a bit of Java knowledge, mine consists of going on a couple of courses a few years ago, but at least I know how to hunt through a bit of Java code, which I had to do in this instance to see how RTD had named this variable/method in the auto-generated Java code.

Now it's just a case of deploying the Inline service, like this:

Once it's deployed OK and with no errors, you can use the Test facility in RTD Studio to test it out. I input a manufacturer_id of 1, and get back the correct results.

OK, so where does this leave us?

  1. Firstly, we know we can look up details of a manufacturer given a manufacturer ID. HOWEVER, I'm not sure whether this is in fact what we should be doing - we need some metrics on manufacturers to feed into the predictive model, but then again it's the manufacturer we're choosing at the end, I'm not sure whether we get the manufacturers attributes from a table like this, or whether they come from the predictive model - we'll have to wait and see.
  2. I've defined entities and session variables for customers and orders, but as yet haven't populated them, as I'm planning to get the BPEL process calling the RTD Inline Service to provide these values as input parameters. I'm not discounting the option, though, of just having the BPEL process pass across the customer ID and order ID, and have RTD get the rest o of the customer and order details from database tables, like we did with manufacturer. This would fit the OTN Oracle-by-example better, but in the scenario I'm trying to built, it'd be more logical to get the BPEL process to provide these values, as it holds them as part of the order it's processing.

So, some good progress but a few questions that I still need to answer. Tomorrow, I'm going to create some informants for the external systems - the BPEL process, the feedback at the end of the customer order and so on, which should well answer these outstanding questions. Check back tomorrow for some more progress.