[Top] [Prev] [Next] [Bottom]


Configuring Channels and Datafeeds

In IntelliPortal, a channel is a path to an end-user client machine and a datafeed is a path to cache or to an external data source. An adapter is an interface between the datafeed and an extension that actually retrieves the external data. This section explains how to create channel and datafeed records for channels that are built by developers.

Adapters and datafeeds work together and can be viewed as a single entity. (This is explained in more detail in Adapters, Datafeeds, and Channels.) The Server Administrator is the application used to manage these channels and datafeeds. It uses channel records and datafeed records to manage these objects. For this to happen, you need to create corresponding channel records and datafeed records using the Server Administrator.

Note that all channels can use datafeeds; they are not confined to Java channels. For example, an HTML channel can be configured to fetch new HTML pages from an external source at regular intervals. It needs a datafeed to do this.

The Configurators menu item on the Server Administrator lets you dynamically add or change channel and datafeed records and commit them to a server. A key feature of IntelliPortal is that you can dynamically add or change channels and datafeeds without starting or stopping the server.

___________________________________

Topics in this section

Configuration Overview

All of the following basic steps are typically needed to configure and publish a channel that can access external data. Many of the steps may be done concurrently, by different developers, and the actual sequence may vary, but each step is required.

  1. Define your requirements in the end user channel to which a user may subscribe.
  2. Decide what the client and adapter exchange (Strings, serialized objects, arrays of objects, etc.).
  3. Write the adapter code (if a pre-built adapter is not adequate) as explained in the Channel Developer Guide.
  4. Add the adapter to the outside_classes directory on the server and then associate it with a datafeed using the Server Administrator.
  5. Again using the Server Administrator, add a channel record for the channel and a datafeed record for the channel.
  6. Write the Java code for the channel.
  7. Publish and test the channel.

How Adapters Work

To create the adapter, you implement IAdapter as explained in the Channel Developer Guide; this makes the adapter usable by the datafeed. The backend of the adapter (the extension) is custom code, created by a channel developer. Then you run the Server Administrator and enter specific metadata such as the datafeed name, how often the data changes, etc.

All external adapter files must reside in the outside_classes directory which is created on the server when the system is installed. This directory includes pre-built adapters URLAdapter and FileReaderAdapter and is also used for additional adapters created by developers. The Java code that implements IAdapter must be written and added to this directory; this is where the server looks for external adapters.

There are three interrelated steps in adapter development:

  1. Write a new adapter (or use a pre-built adapter) for access to external data.
  2. Put the adapter file in the outside_classes directory.
  3. Configure the channel and datafeed records.

When the IntelliPortal server starts, it first reads the property files in the user's etc directory. These files provide information on such things as how to connect to the database, proxy information, and various startup parameters. Next, it reads the metadata (if applicable). Metadata is data about data. For transmitters, this includes information about channels, adapters, and the characteristics of data being stored on the server. This metadata is configurable and can be dynamically changed while the server is running. This means you can add, delete, and modify channels and datafeeds, and their behavior, without stopping the server.

When you commit a change, the metadata is changed, any interested parties (i.e. running transmitters) are notified, and the changes are logged. This log is located in the IntelliPortal logs directory and named MetaDataChanges.log. It is written in SQL format so that it can be used to re-apply these same administrative changes at some later time.

Data That Adapters Retrieve

During channel updates, various types of data are passed from the server to the client. When configuring channel records and datafeed records as explained on the following pages, it is important to understand the different types of data that are accessible from the server during channel updates.

Data That Adapters Retrieve Description
Generic Data Static data distributed to all clients. This is distributed to all clients that are subscribers to a given channel during an update. Examples are Java class file, gifs, HTML code, etc.
Custom Data Dynamic data distributed only when requested. This is dynamic data that is available to all clients that are subscribers to a given channel but it is only sent to a user when specifically requested. For example, a company news channel might contain news stories for most publicly traded companies. Rather than getting data for all publicly traded companies, an end user can receive a subset of the data (e.g. IBM and Netscape).
User Specific Data Data directed to a specific user. This is data for a specific user such as a statement download, e-mail, or the status of a mortgage application.
Usage Tracking Data Data about end users. This is data collected about end user behavior (with pre-defined criteria) and sent to the server. This information is available through the Usage Tracking adapter and can be sent to a commercial ad server.

Creating Channel Records

Channel configuration is closely associated with the adapter and datafeed configuration. Adapters are used by channels to fetch data from outside the IntelliPortal server; datafeeds manage that data once it has been fetched. This section explains channel records and their association with datafeeds.

You must create a channel record for any channel that has a datafeed, that is for any channel that accesses external data. If a channel doesn't have a datafeed, the channel record is optional.

A channel can access data through datafeeds to provide Channel Custom Data and User Specific Data to a client (and Usage Tracking Data if desired). Using this metadata, any number of datafeeds can be associated with a channel. They can be grouped together for convenience, and different chunks of data can be sent to different datafeeds in a defined group. Without programming and using a channel's associated datafeed, a client may send the following to adapters:

Additionally, once the data is fetched, it is placed in a file whose name is determined by the metadata. This name can be automatically modified and made unique for multiple, indeterminate numbers of returned files. Any exceptions on the server that can be caught are placed in UpdateExceptions.txt and returned for debugging.

As show in the Channel Configurator window, channel records have two parts.

Static channel data is simply high-level metadata that describes the channel. Dynamic channel data is used to associate datafeeds with a channel. There can be any number of these records per channel and this information is used to associate those datafeeds with a channel. The datafeed is associated with an adapter and is the mechanism for sending any Custom Channel Data and User Specific Data to a client. Typically, information on the client is added using the IRequestBuffer service and is destined for a given datafeed. Once the datafeed gets that information, it can use it to get any Custom Channel Data and User Specific Data, and return it to the client in a file. This information in the configurator manages this association.

Adding, Modifying, and Deleting Records

Use the following procedures to add, modify, or delete records, using standard Windows techniques to navigate in the Configurator windows. Note that there are two ways to add a record: (1) you can add a new record or (2) you can simply rename or copy an existing record.

To add a record
  1. Select New from the Configurators menu.
  2. Select a hostname.
  3. Select a record type (channels or datafeed).
  4. Enter a unique name. (This adds the record to the tree in the left pane.)
  5. Configure the record fields as explained below. (If necessary, click Add Record to add additional datafeeds to a channel record.)
  6. When done, select Commit from Configurators menu and wait for status message.
To modify a record
  1. Right-click on record and choose Rename, Copy, or Delete.
  2. Configure the record fields as explained on the following pages. (If necessary, click Add Record to add additional datafeeds to a channel record.)
  3. When done, select Commit from Configurators menu and wait for status message.

Channel Configurator

Channel Field Description
Channel Name Unique name for this channel. This name must be the same as the channel's published name.
Description Descriptive text for the channel. A string that serves as a description of what the channel is used for.
Delete Record Permanently deletes the record from the system when checked and committed. Use with caution.
Data is active Uncheck to make the channel's metadata record inactive and inaccessible; does not delete the record entirely. This means that only generic channel data is accessible; Custom Channel Data and User Specific data are not.
Require Enrollment If set, this allows only enrolled users access to the Custom Channel Data and User Specific data this channel can send. An enrollment channel is an example where all users would need access in order to enroll. If only enrolled users had access, no one could enroll.
Debug Individual channels can be coded to generate debug data. This checkbox determines whether or not that data is written to the java.out log; if not checked, no data is logged. All channels use the same log; right-click on the transmitter name and select View Output to display it.
New A read-only field that is checked if the record is new.
Name to map to

· The Custom Channel Data and User Specific data that a datafeed sends back ultimately becomes a file in the client's channel directory. This variable sets that filename. There are numerous options although the base functionality is usually adequate:

· Using a name with no special characters in it (defined below) places the data in a file of the given name. For example, the string: OfxData.txt creates a file with OfxData.txt on the client with the data from the associated datafeed in it.

· Having a delimiter character in the name (defined in the delimiter field below) substitutes the chunk of data from the client into the string. For example, if the delimiter character is ~, the name to map to is ~_News.html, and the chunk of data from the client is meca, then the resulting file is named meca_News.html. In addition, if the chunk of data from the client also contains the delimiter character, it is parsed and inserted into the name to map to string in the corresponding place. This means that the first token replaces the first delimiter, the second replaces the second, etc. For example: Still using the ~ delimiter example above, if the name to map to is ~_News.~ and the chunk of data from the client is meca~html, then the file meca_News.html is generated. Note that if there are not enough tokens to be placed in the name to map to string, the last one is repeated. Also note, this is not connected to the token determined on the client using the IRequestBufferService; that token is used to create chunks of data to be sent to an adapter. This delimiter tokenizes the chunk into yet smaller pieces for the purpose of naming the returned file. Finally, this is also different from the delimiter character in the adapters and datafeeds section which is used to create a unique request for an adapter.

· A datafeed may return more than one file and this number may vary from call to call. Thus a construct is used to create unique names for each file returned by a single datafeed. If a # character is used in the name to map to string, then the index number of the returned file (starting with zero) is used to replace the # character. So if the name to map to is NewsStory_#.html and there are three files returned, they are named NewsStory_0.html, NewsStory_1.html, and NewsStory_2.html. Note that if a datafeed returns multiple files and this construct is not used, the contents of the last file are returned in the given name. This can also be used for datafeeds returning a single file; the substitution is always be zero.

· Leaving the name blank uses the uniquely constructed name sent to the adapter. Note that for some applications, the name an adapter uses may have no meaning in the outside world.

· Having a * in the name to map replaces the * with the uniquely constructed name sent to the adapter. Again, for some applications, the name an adapter uses may have no meaning in the outside world.

Delete Permanently deletes the record from the system when checked and committed. Use with caution.
Active Makes the association to the datafeed for this channel inactive and inaccessible but does not delete the record entirely. This means that this adapter does not send data to the client. This can be used to stop sending a particular piece of data to a client while not having to stop the entire channel. For example, if a channel sends several different types of financial data to a client and one of the multiple sources for this data goes down, you can set this flag to inactive to stop requests for that specific information while allowing the rest of the channel to update normally. Once the data access is restored, it can be re-activated.
All Updates Generally, adapters use information from the client to fulfill a request. This is not always the case. There are adapters you may want to call for all channel updates with no arguments, regardless of whether there is any data in the adapter. stream. Setting this flag will make this datafeed called for all updates, with no arguments passed to it. An example of this may be for a datafeed that returns a targeted advertisement, fetched from a commercial ad server. Here, no information is needed from the client to fetch the data. The only needed information is the user's ID which is automatically accessible by the adapter. With that ID, the adapter can make a request from the ad server for the proper data.
Description Descriptive text for this channel/datafeed relationship.
Delimiter The delimiter used in name to map to discussed above.
Group Name The datafeeds available to a channel can be grouped. This means that a given channel can send multiple pieces of data to the server using the IRequestBufferService and target them to different datafeeds. For example, a given channel can supply company news, current stock price, and both yearly and monthly graphs of the stock's price history. If the channel developer wanted to make different requests for each of these services, they could use a group name. For example, the group for the company news datafeed would be NEWS, the quote price datafeed would be QUOTE, and the datafeeds for the two graphs would be GRAPHS. Now, on the client, if the New request was for IBM, this would be added using IRequestBufferService (assuming buf is that buffer object): buf.add("NEWS", "IBM"); Now assume quotes were wanted for IBM, SUNW, and NEC using a space as a chunk delimiter. This would be added as follows. buf.add("QUOTE", "IBM SUNW NEC", ` `); Lastly, assume a graph was desired for SUNW: buf.add("GRAPHS", "SUNW"); This would channel the appropriate chunks of data to the desired datafeeds as determined by the group name. Typically, grouping the datafeeds is unnecessary, so the default group (called DEFAULT) is used and is the target for all requests added without a group. In the above example, assume the same ticker request was always sent to all datafeeds. In this case, if you leave the group name as DEFAULT and use IRequestBufferService without a group name, it sends the chunks of data (delimited by a space) to all datafeeds. buf.add( "IBM SUNW NEC", ` `);

Group names have the following rules:
  • Any datafeed with All Updates checked is always called for during all updates even if there is no data in the request buffer. The group name has no effect here.
  • By default, the datafeed will have the DEFAULT group name. This means any request from the client that is not explicitly given a group name will go to them.
  • If a group name is entered for a datafeed overriding DEFAULT, then the datafeed gets only the requests that were explicitly added to the client's request buffer with an exactly matching group name.
  • If a group name is entered for the datafeed and no exactly matching request is made, the datafeed is not called.
  • If a client uses a group name for data it added to the request buffer, and there is no corresponding data feed with a matching group name, the request is ignored; it does not go to the default.
Datafeed ID The name of the datafeed to associate with this channel. This must exactly match the Name field in the adapters and datafeeds section. Once an adapter/datafeed is set up, this is where it gets associated with a channel.
Disposition The Marimba dispositions for sending the file to the client are explained below.
  • If_Needed - Send the byte array to the tuner only if the tuner doesn't already have the data. The data is sent as immediate data which means it will not be cached by a Marimba proxy. This data will be part of the channel's index and will have an effect on optimized update requests.
  • Always - Always send the byte array (file) to the tuner on every request. The data is sent as immediate data which means it will not be cached by a Marimba proxy. This file is not part of the channel's index and will have no effect on optimized updates.
  • Persistent - Treats this byte array as though it were a file. It makes the byte array persistent (for a limited amount of time - at least five minutes) so that the request for this data can be satisfied in a subsequent request by a tuner (or proxy) without plugin intervention.
  • The two dispositions used in all cases are Always and If_Needed. Always sends the file even if an identical file already exists. If_Needed only sends the file if it does not exist (or if it does exist and has changed). Note that if a channel developer deletes a file received from the server, the identical file will be sent during a new update. If If_Needed is used, it will not be re-sent; it will only be re-sent with Always.

Creating Datafeed Records

Datafeed configuration is closely associated with channel configuration. When an adapter is called, it will generally require input (from the client) to uniquely fulfill the request for data. There are three ways you can do this.

If you send data directly from the client to the server using the client's IRequestBufferService, the data can sent directly to the adapter with no modification. Any kind of data may be sent this way, e.g. a String, byte array, OFX stream, or serialized object.

In other cases, you might want to insert the information from the client in the form of a string into a pre-defined String on the server to make the request unique. This is done by having a Target Name (see below) defined for the adapter that contains special characters that are replaced with the information received from the client. The most common example of this is a URL string. For example, if there is an adapter that returns a web home page through HTTP and the special delimiting character is *. The target string might be http://www.*.com. Now if the client sent the string mecasw via the IRequestBufferService, the adapter would receive the string http://www.mecasw.com. This facility is particularly useful with the URLAdapter or any adapter using URLs to connect to legacy data.

You can also associate multiple adapters with a single channel to let the client assemble the data it sends through IRequestBufferService into different groups. On the server, these groups are associated with some subset of the adapters associated with that channel. Thus in a single update for a given channel, the client could send several groups of totally different data to the server, which would then be sent to the correct adapter used to fulfill the request.

By using datafeed configuration, you add an adapter and determine how the data it receives will be managed. Part of the function of channel management is to associate this data (through datafeeds) with a channel update request. This assumes that the adapter is an IntelliPortal adapter, or one you developed and put in the outside_classes directory.

The procedures to add or modify datafeed records are the same as those for channel records. See Adding, Modifying, and Deleting Records for details.

Datafeed Configurator

Datafeed Field Description
Datafeed Name A unique name for this datafeed. You can have any number of datafeeds associated with a single adapter. For example, the URLAdapter can have different datafeeds to access different types of data that are available through URLs.
Description Descriptive text for the datafeed. Typically, a String that serves as a description of what the datafeed is used for.
Delete Record Permanently deletes the record from the system when checked and committed. Use with caution.
Data is active Used to make the datafeed inactive and not accessible. Does not delete the record entirely.
Adapter Class The fully qualified classname of the adapter associated with this datafeed. If this datafeed uses adapter called com.mecasw.TestAdapter.class, and the code is placed in the outside_classes directory in outside_classes/com/mecasw/directory, the entry in this field would be com.mecasw.TestAdapter. When the record is saved, this adapter is loaded when this datafeed needs data from outside IntelliPortal.

Adapters can be handed an AdapterContext object. When an existing record is read, the adapter is queried as to if it wants an AdapterContext handed to it, and if so, what should be in it. If it does want something in AdapterContext, entries show up in the AdapterContext table section of the configurator. The entries can be, in addition to other things, a host adapter or a class. These in turn may also require some AdapterContext entries. Those values also show up.
Target Name If the adapter receives a String as a target to satisfy this datafeed, this is the String that is either always the same or has some component that is the same. It may contain special delimiter characters that are replaced by chunks of data that the client sends.
Delimiter Character If the TargetName string is set, and you wish to insert some string(s) from the client into it via the IRequestBufferService to make the request unique, they will be replaced with the chunk of data from the client if any of the characters chosen are in the TargetName. For example, assume there is an adapter that returns a web home page through HTTP and the special delimiter character is *. The target string might be http://www.*.com. Now if the client sent the string meca via the IRequestBufferService, the adapter would receive the string http://www.meca.com.

You can have multiple substitutions in a given string with multiple values. The chunk of data from the client is broken up by the same delimiter character. Using the same web home page example, the TargetString could be: http://www.*.*, and if the chunk of data from the client was meca*com, the string would expand to http://www.meca.com. If the string from the client was pbs*org, the TargetString would expand to http://www.pbs.org.
Multiple Chunks Generally, data is returned as a single thing, e.g. a web page, a serialized object, or an OFX file. However, you can have an adapter return a bundle of things, e.g. news stories for a particular company being sent as web pages. By checking this option, multiple web pages are returned as separate files with one call to the adapter (see the javadocs for com.mecasw.eb.datafeed.DataBundle for details on implementing this programmatically.)
Frequency of change The IntelliPortal server can cache data locally that was previously fetched from adapters. This can significantly reduce the time and processing needed to send data to end users. For example, you may want to cache the current mortgage interest rate that changes only once every 24 hours. If there were 10,000 hits a day for that information without caching, each hit would require a request through an adapter to the legacy system. With caching, there is only one request to the legacy system per day.

Caching is especially useful for (1) reducing manipulation of large pieces of data; (2) data requiring a process-intensive operation to acquire (it reduces the response time to client and increases efficiency of the server and legacy systems); (3) highly requested data (reduces the sheer number of hits to the legacy system); (4) infrequently changing data. This field controls if and how the data is cached. There are five caching options:
  • Always - Always get it from the adapter; this data is not cached.
  • Never Expire - Always get it from cache. If there no data in the cache, get it from the adapter. The data never expires. If not found either in cache or from the adapter, null is returned.
  • Scheduled - Never get it from the adapter. Similar to Never Expire except the data in cache does change and is placed there by some external process.
  • Sometimes - Always check cache. If found, see if the data is stale by checking Rate in seconds setting. If stale, get from adapter. An exception is thrown if the data is stale and new data can't be retrieved from the adapter.
  • If Available - Always check cache. Similar to Sometimes, except if stale, use cache anyway. An exception is thrown only if no data is found.
Rate in seconds If you cache the data with Sometimes or If available above, this field determines how long the data is considered fresh. So, if data is fetched from an adapter and is set for caching, and the change rate is one hour, any subsequent request from a client for that data will be satisfied from cache for the next hour. The first request for the data after it becomes stale will prompt the server to get fresh data from the adapter and cache it. Again, for the next hour, the data will come from cache. If desired, the starting or creation time of the data can be set by the adapter developer. If not, by default, the creation time is when the data is retrieved from the adapter.
Adapter Context When an existing record is read, the adapter class is queried to find out if it requires any data be inserted in its AdapterContext. For each piece of data required, there will be one line in the table. The information here is saved only if the data field has a value. The data field may contain other classes used by the adapter. These may also require AdapterContext entries. They are also queried to see if they require any entries, and if so, they are listed here too. All fields are read only except for the data field which may be read/write. See the Developing Adapters section of the Channel Developer Guide for more information.
Status For any existing records (those where the data field has a value), the adapter is queried to check the status of this entry. There are three possible values:
  • CONFIRMED - The query to the adapter or class confirmed that this entry is in fact used.
  • UNCONFIRMED - The adapter or class could not be accessed by the server so this entry could not be confirmed as being used.
  • UNREACHABLE - The adapter or class does not use this entry. This means that if an adapter had used an AdapterContext entry called URL, and there was a record entry here for it, and now the adapter was changed and no longer uses URL, this would cause the flag UNREACHABLE to be displayed. If it is true that this will no longer be needed, delete the data value and the record will be deleted.
Consumer Class As discussed, the adapter may be handed other classes. These other classes may also require adapter context records which will be displayed here. This field shows the name of the class that actually uses this entry: the consumer of this record.
Type of Data
  • hostadapter - Often there are two parts to an adapter, a generic part which provides some basic functionality or services, and a host-specific part for connecting to and communicating with something outside the IntelliPortal server. Through this metadata, a single generic part can be handed different host-specific parts in its AdapterContext. This type is reserved for classes used by adapters for host-specific activities. An example is the FinancialAdapter. Here the actual adapter provides basic generic financial information. Once processed, it is handed to the hostadapter it received in its AdapterContext. This can be a URL connector, a socket connector, or some custom host communication piece. An instantiation of this is handed to the consumer class.
  • object - Any other object needed by the adapter. An instantiation of this is handed to the consumer class.
  • userid - This is the userid of the client on whose behalf this adapter instance is executing. This value is set by the server before calling the adapter, and therefore this will render the data field non-editable.
  • PropertyFile - A java.util.Property class is instantiated and placed in the AdapterContext. The name of the property file is specified in the Data field. The file must reside in $MECA_HOME/etc
  • String - A java.lang.String whose value is the string entered in the Data field.
  • timestamp - This is set by the adapter and read by the server. It represents the time that the data returned by the adapter was created. This will render the data field non-editable.
Key The adapter or class must specify a key name for each piece of data. This is that key name.
Data This is where the administrator enters the information for this entry. For example, if this is a hostadapter, this field may be com.mecasw.util.HTTPConnector. If this were a String and key was a URL, this may be http://www.mecasw.com.

Configuration Examples

The following examples show the process needed to develop some typical adapters. The following high level steps are required to accomplish this, although many of these steps can be done concurrently. See the Channel Developer Guide for a wider discussion of adapter development.

  1. Define the desired client functionality. (This is what the end user sees when they subscribe to a IntelliPortal channel.)
  2. Define the client and adapter functionality, and what the client and adapter send to each other (strings, serialized objects, arrays of objects, etc.).
  3. Write the adapter code (if a pre-built adapter is not adequate).
  4. Using the Server Administrator, add the adapter to the server using the datafeed configurator.
  5. Using the Server Administrator, add a channel record for the channel with the channel configurator. This associates the datafeed from above with the channel.
  6. Write the actual Java code for the channel.
  7. Publish and test the channel.

AnswerMyQuestion Channel and Adapter - Simple Example

In this example, the client channel submits a question to the IntelliPortal server, and that question is sent to an adapter for an answer. The response is returned in the file Answer.txt. There are many ways to do this, but for this example, the client will add a String to the IRequestBufferService, and the adapter will be handed this String which it will answer by sending a String back. For simplicity, only two possible questions are asked, "What is the Date and Time?" or "What is your Name?". This completes the first two steps defined above.

Next write the adapter. Normally, an adapter will use the information it received to get information from outside the IntelliPortal server to fulfill the request. In this case, the adapter (com.test.adapters.AnswerQuestionAdapter.java) will only do the following.

public Object process(Object obj) throws AdapterException
{
    String question = (String)obj;
      
    if(question.equals("What is the Date and Time?"))
        return(new String("The Date and Time is " + new Date));
    else // What is your name?
        return("My name is QuestionAnswerAdapter");
}

When done, put the adapter in the outside_classes directory on the server and use the Server Administrator to add it. First we configure the datafeed and adapter. We create a new datafeed record, overriding the defaults, as follows.

Datafeed Record
Datafeed Name QuestionAndAnswer
Description A demonstration adapter to show request and response functionality.
Data is active Check this to make the adapter available.
Adapter Class com.test.adapters.AnswerQuestionAdapter
Multiple chunks No
Frequency of Change Always. For this example, we want the data to always come from the adapter.

Next, create a new channel record, overridng the defaults as follows.

Channel Record
Datafeed Name AnswerMyQuestion
Description A demonstration channel used to show how information flows from client to server and back.
Data is active Yes
Require Enrollment No. For this example, don't care.

Next, for the channel, we create one new dynamic channel data record, associating the adapter/datafeed with this channel.

Dynamic Channel Data
Name to Map to Answer.txt
Active Yes
All updates No
Description Datafeed used to answer the question coming from the client.
Delimiter Leave blank.
Group Name Leave as DEFAULT.
DataFeed Id QuestionAndAnswer. The Name used when creating the datafeed/adapter information.
Disposition ALWAYS. We will always send the file.

This is all you need. The server is ready. If the client, using the IRequestBufferService, does this:

buf.add("What is the Date and Time?");

A file called Answer.txt is returned with the string:

"The Date and Time is Tuesday December 7, 1999 07:21:02".

If the client sends this:

buf.add("What is your Name?");

A file called Answer.txt is returned with the string:

"My name is QuestionAnswerAdapter".

AnswerMyQuestion Channel and Adapter - Complex Example

The first example asked a single question. If the client adds more than one question in a single update, only the answer to the last is returned to the client. This is because the metadata is set up so that the response to the question goes into a single file called Answer.txt. Each time a datafeed returns a response to the plugin, it overwrites the previous file with the contents of the new file. In the next example, we will allow multiple questions. There are several potential ways to do this and the following two examples are discussed:

One File Returned for Each Answer

The first method only requires a metadata change and one of several naming options that are available. This only shows those fields different than the first example. First, we set up the metadata so that the returned files will be the same as the question asked.

Datafeed Record No modifications necessary
Channel Record No modifications necessary
Dynamic Channel Data Name to map to: Leave blank

This tells the plugin to use the unique identifier that was sent to the adapter to fulfill the request. The unique identifier sent to the adapter is the question (in the form of a string).

If the client, using the IRequestBufferService, does this:

buf.add("What is the Date and Time?");

A file called What is the Date and Time? is returned with the string:

"The Date and Time is Tuesday December 7, 1999 07:21:02".

If the client sends this:

buf.add("What is your Name?");

A file called What is your Name? is returned with the string:

"My name is QuestionAnswerAdapter".

Here is a variation.

Datafeed Record No modifications necessary
Channel Record No modifications necessary
Dynamic Channel Data Name to map to: *.txt

This tells the plugin to use the unique identifier that was sent to the adapter in place of the * character in the Name to map to. The unique identifier is sent to the adapter if the question is in the form of a string.

If the client, using the IRequestBufferService, and does this:

buf.add("What is the Date and Time?");

A file called What is the Date and Time?.txt is returned with the string:

"The Date and Time is Tuesday December 7, 1999 07:21:02".

If the client sends this:

buf.add("What is your Name?");

A file called What is your Name?.txt is returned with the string:

"My name is QuestionAnswerAdapter".

The next option for a multiple file return is to have the adapter return a DataBundle. The DataBundle lets an adapter return any number of distinctly different pieces with one call and return. The client code concatenates each question into one request, and those concatenated questions represent one chunk of data. The questions are parsed by the adapter; each question is answered and that answer is added to the DataBundle, and the DataBundle is returned. The answers are placed in files called Answer0.txt, Answer1.txt, Answer2.txt, etc. Again, only the changes from the initial simple example are shown:

Datafeed Record Multiple chunks: Yes
Channel Record No changes.
Dynamic Channel Data Name to Map to: Answer#.txt

This tells the plugin to replace the # with the index number for that particular piece of data from the adapter. Assume the adapter parses the questions by the ? character. If the client, using the IRequestBufferService, does this:

buf.add("What is the Date and Time? What is your Name?");

A file called Answer0.txt is returned with the string:

"The Date and Time is Tuesday December 7, 1999 07:21:02".

And a file called Answer1.txt is returned with the string:

"My name is QuestionAnswerAdapter".

One File Returned for All Answers

None of these variations requires metadata changes from the initial simple example. All changes are code changes depending on the desired functionality. The coding details are not shown but it demonstrates the versatility of what can be sent through the IntelliPortal server.

First, as in the last example above, the client concatenates multiple questions into one request, and the adapter parses them into separate questions. In this case it answers each question, concatenates the answers, and sends back one response. That response becomes Answer.txt.

In the next example, a serialized object is added on the client, and the adapter de-serializes it, extracts the information, and responds by concatenating the strings together like above. The client code to add the object might look like this:

Vector v = new Vector()
v.addElement("What is the Date and Time?");
v.addElement("What is your Name?");
buf.add(MECAUtil.objectToByteArray(v));

Lastly, the adapter could have inserted the answers in an Object like a Vector, and serialized and returned it, instead of sending concatenated strings. The server would place the serialized Object in the file, and the client would de-serialized it and extract the information accordingly.

AnswerMyQuestion - Using Cache

In previous examples, all requests went directly to the adapter without using cache. The next two examples demonstrate hot to use cache and also how dissimilar pieces of data can be grouped together. Looking at the answers to the possible questions, the answer to "What is the Date and Time?" will always change and can't be cached. The answer to "What is your Name?" never changes and can be cached.

To do this, we set up two different datafeeds, one for the Date and Time, and one for Name. They will both use the same adapter but will manage the data that is returned differently. In the channel record, we will use grouping so the right question goes to the right adapter. The datafeed/adapter records are essentially the same as in the original simple example with some minor changes. Listed below are all modified fields that differ from the default.

This is the adapter/datafeed entry for the DateTime datafeed:

Datafeed Record
Name DateTimeQuestionAdapter
Description This will return the DateTime when asked.
Data is active Check this to make the adapter available.
Adapter Class com.test.adapters.AnswerQuestionAdapter
Multiple chunks No
Frequency of Change Always. We want the question to always go to the adapter.

This is the adapter/datafeed entry for the Name datafeed:

Datafeed Record
Name NameQuestionAdapter
Description This will return the name of the adapter when asked.
Data is active Check this to make the adapter available.
Adapter Class com.test.adapters.AnswerQuestionAdapter
Multiple chunks No
Frequency of Change Never Expire. Always use cache. We don't need this information from the adapter unless not in cache. This means the first time asked, it will not be in cache so the adapter will be asked the question. The response will be put in cache for answering subsequent calls. All subsequent requests will not require a call to the adapter.

Next, create a new channel record. This is exactly the same as the simple example shown earlier. Listed below are the settings to override the defaults:

Channel Record
Name AnswerMyQuestion
Description A demonstration channel used to show how information flows from client to server and back.
Data is active Yes
Require Enrollment No. For this example, don't care.

Next, for the channel, we create one new channel dynamic data record for each of the two datafeeds we want to access. They are similar to the simple example, except that we now use group names and associate them with the appropriate datafeed. First the DateTime record:

Dynamic Channel Data
Name to Map to DateTimeAnswer.txt
Active Yes
All updates No
Description Datafeed used to answer the question coming from the client.
Delimiter Leave blank.
Group Name DATETIME We want all data coming from the client associated with the DATETIME group to come to this adapter.
DataFeed Id DateTimeQuestionAdapter The Name of the adapter/datafeed to go to.
Disposition Always. Always send the file.

Next the Name record:

Dynamic Channel Data
Name to Map to NameAnswer.txt
Active Yes
All updates No
Description Datafeed used to answer the question coming from the client.
Delimiter Leave blank
Group Name NAME.We want all data coming from the client associated with the NAME group to come to this adapter.
DataFeed Id NameQuestionAdapter The Name of the adapter/datafeed to go to.
Disposition ALWAYS Always send the file.

The questions are now grouped on the client side when making requests. Note that this is a simple example. In a more complex example, any number of chunks of data (e.g. questions) could be sent to each of the groups. Note that since there is no adapter set up as the DEFAULT, if no group name is specified, the request would be discarded once it arrived at the server. Here is the client piece:

If the client, using the IRequestBufferService, does this:

buf.add("What is the Date and Time?", "DATE");

A file called DateTimeAnswer.txt? is returned with the string:

"The DateTime is Tuesday December 7, 1999 07:21:00".

The request would have gone directly to the adapter without using cache.

If the client sends this:

buf.add("What is your Name?", "NAME");

A file called NameAnswer.txt is returned with the string:

"My name is QuestionAnswerAdapter".

If this was the first request to the server for this information, the server would have checked cache, and found that there was no data; then it would have sent the question to the adapter which would have returned the answer. The answer would have been placed in cache so that subsequent requests would have found the result without contacting the adapter.

AnswerMyQuestion - Using Cache with Expiring Data

This example is similar to the cache example above but shows how to set up data that is cached and then expires. To do this, assume that the question is changed to "What is the Date?" (not the date and time). The date is the same for 24 hours, so we set up the datafeed to keep and use the cached data for 24 hours after which it expires and must be re-fetched from the adapter. This means that the adapter would only be hit once per day, for any number of requests from that datafeed for that information.

When data is returned from an adapter, it is associated with a creation time. If the data is set to expire, this time is used to set a start point for determining when the data is stale. By default, if the adapter does not explicitly set a creation time, the time the record was fetched from the adapter is used. In this case, the adapter needs to explicitly set that time.

If the first request for the date arrives at 1:00 AM, the default creation time would not be correct because it would be one hour after the date change; the data would be stale in 23 hours rather than 24. So the adapter would set the creation time to the current time minus the number of total seconds past midnight. This would be done by using the AdapterContext that is available to all adapters and is used to get and set required information. (See the Channel Developer Guide for more details.) The changes would consist of writing the adapter, and minor differences in the adapter/datafeed entry from the above example.

This is the adapter/datafeed entry for the Date datafeed:

Datafeed Record
Name DateQuestionAdapter
Description This returns today's date when asked. The date is good for 24 hours and the cache is set for that.
Data is active Check this to make the adapter available.
Adapter Class com.test.adapters.AnswerQuestionAdapter
Multiple chunks No
Frequency of Change Sometimes. This means to check cache. If there is data in cache, determine if it is fresh enough to use. This is determined by the Rate in Seconds.
Rate in Seconds 86400 This is the number of seconds in 24 hours. Use if required by the Frequency of Change. This means the data changes every 86400 seconds, so that 86400 seconds after the creation time of the data in cache, the adapter would need to be accessed again.

All other factors are essentially the same. The same adapter can be used for any of these types of caching, with no prior knowledge of whether or not the data is cached.



[Top] [Prev] [Next] [Bottom]


documentation@mecasw.com
Copyright © 1999, MECA Software L.L.C. All rights reserved.