Developing Your Own Web Application Server™ Cartridge: Release 3.0.2
Developing Your Own Web Application Server™ Cartridge: Release 3.0.2
Web Application
Server™ Cartridge
Release 3.0.2
Contents vii
WRB_ICXdestroyRequest(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-4
WRB_ICXfetchMoreData() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-5
WRB_ICXgetHeaderVal() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-7
WRB_ICXgetInfo() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-8
WRB_ICXgetParsedHeader() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-9
WRB_ICXmakeRequest() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-10
WRB_ICXsetAuthInfo() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-11
WRB_ICXsetContent() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-12
WRB_ICXsetHeader() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-13
WRB_ICXsetMethod() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-14
WRB_ICXsetNoProxy() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-15
WRB_ICXsetProxy(). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-16
WRBInfoType Enumerated Type. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-17
WRBMethod Enumerated Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-18
Contents ix
x Developing Your Own Web Application Server™ Cartridges
CHAPTER
The Web Request Broker is the central component of the Oracle Web Application
Server. It is an asynchronous request handler with an API (Application Program
Interface) that enables it to interface dynamically and seamlessly to various back-end
technologies called “WRB Cartridges”. It provides an architecture that allows server-
side web applications to run under any HTTP server to which the WRB has been
ported.
The Web Request Broker offers capabilities similar to CGI scripting. In fact, you can
use the WRB API to access CGI data sent by the client. WRB applications, called
cartridges, however, take advantage of the WRB’s multi-process architecture to get
much better performance than ordinary CGI scripts.
The WRB architecture also makes WRB cartridges extremely scalable—that is, they can
handle small request loads economically and large request loads efficiently.
Whenever the Web Listener receives a URL that calls for the WRB, it passes execution
of the request to the Dispatcher. The Dispatcher determines for which cartridge the
request is intended and directs the WRB to allocate an execution instance (WRBX) of
the cartridge. The Dispatcher then calls the WRBX to handle the request. The result is
that the Listener can receive and validate URLs coming in, while each request is
handed off to a process that executes it in the background.
WRB Architecture
Components:
• The Dispatcher
• The Web Request Broker
• WRB cartridges
• The WRB application engine
• WRB execution instances (WRBXs)
A WRB cartridge is implemented as a shared library that uses the WRB API to handle
HTTP requests from web clients.
The Dispatcher is a program that provides a CORBA interface between Web Listeners,
the Web Request Broker, and WRB cartridges. The Dispatcher manages WRB
cartridges and the requests directed to them. When the Web Listener receives an HTTP
request directed to a WRB cartridge, it forwards the request to the Dispatcher, which
uses its configuration data to map URLs to WRB cartridges.
The WRB application engine is the executable program that implements the WRB API
and runs within each WRBX. It provides the interface between WRB cartridges and the
Dispatcher, directs WRB cartridge flow of control, and provides services for WRB
cartridges to use.
1 2 3b
Client Listener Dispatcher WRB
5 5 3b
3a
The Dispatcher may then forward future requests directly to the cartridge instance and
receive responses directly from it. (This behavior is restricted by the Sessions
mechanism; see Sessions below.)
The WRB configuration data specifies for each cartridge the maximum number of
WRBXs that may run at once, and the minimum number of WRBXs that must always
be running. You can tune your WRB performance by adjusting these values using the
Web Request Broker administration pages.
• Cartridge functions - the interfaces the WRB application engine uses to call your
application.
• WRB application engine functions - the interfaces the WRB application engine
provides for your application to use.
To make your cartridge functions available to the WRB application engine, you store
pointers to the cartridge functions your application defines in a function table (see The
Entry-Point Function in Designing Your Application in the online documentation).
• Content service - provides a common interface for storing web content in the
local file system or a database.
• Intercartridge exchange (ICX) service - provides a mechanism that cartridges
can use to issue requests to other cartridges.
• Transaction service - provides a mechanism for managing database
transactions.
• Logger service - provides a mechanism for logging information to database or
ordinary files.
The WRB application engine functions are declared in the header wrb.h. The function
names all begin with “WRB”. APIs belonging to services are declared in other header
files, and these files are included by wrb.h.
The WRB API in wrb.h needs to clarify that WRB_walkPBlock does not necessarily
iterate through the elements in the header in order.
The content service allows you to make changes to a local copy of a document in a
repository and apply those changes to the original document whenever you choose.
Note: Currently, you cannot use the Transaction Service with the Content Service. And
Content Services, an advanced feature of Oracle Web Application Server, requires
Oracle RDBMS 7.3 or higher.
See the WRB Content Service API Reference for more information.
However, ICX will not work between cartridges running on NT and on UNIX. So, a
cartridge running on NT cannot communicate with another cartridge running on
UNIX, and vice-versa.
For more information, see WRB Architecture in Designing Your Application and the WRB
Intercartridge Exchange Service API Reference in the online documentation.
See the WRB Transaction Service API Reference in the Oracle Web Application Server
online documentation for more information.
Sessions
The WRB architecture provides a mechanism for associating a web client with a
particular WRBX. This association, called a session, allows WRB cartridge developers
to write cartridges that maintain client state data that remains valid from request to
request, because each session-enabled cartridge execution instance receives requests
from one and only one client.
See Maintaining Persistent Client State in Designing Your Application in the online
documentation for more information.
• Prompt for a username and password, using either a Basic or a Digest scheme.
The difference between Basic and Digest authentication is that Digest encrypts
passwords (for more information on these terms, see Introduction to Oracle Web
Application Server).
• Specify by name some restriction scheme to be applied to this request. Such
restriction schemes are defined in the Listener and limit access by IP address or
Domain Name.
• Get the client-side certificate. See WRB_getClientCert() for details.
For more information on how WRB cartridges work and how to write your own, refer
to the WRB specification that accompanies the Web Application Server online
documentation.
This chapter describes the steps involved in writing a server-side web application,
called a Web cartridge, using the Web Request Broker (WRB) API.
Upgrading Note: Any custom cartridge built using a 2.x or 3.0.0.x WRB API must be recompiled using a
3.0.1.x and above WRB API.
Contents
• Designing a Web Cartridge
• Upgrading from the WRB 2.x API to the WRB 3.0 API
• Callback Functions in a Web Cartridge
• Data Flow of a Typical Request
• Compiling, Linking, Configuring, and Running a Web Cartridge
• Modifying Your Web Cartridge
• Debugging Your Web Cartridge
• The Entry-Point Function
• The Init Function
• The Authorize Function
• The Exec Function
• The Shutdown Function
• The Reload Function
• The Version Function
• The Version_Free Function
• WRBReturnCode enum
For a general overview of the Web Request Broker architecture under which
cartridges run, see Overview of the Web Request Broker (WRB).
Designing a Web Cartridge
This section discusses concepts you should consider before starting to write your Web
cartridge, such as common Web cartridge programming models.
To write a cartridge of this type, you can code your Exec function to identify the
request, respond with the requested content, and return without saving any state.
In writing a cartridge of this type, you can code your Exec function to save client-
related state data in your application context structure, which is local to each
cartridge instance. Because the sessions mechanism guarantees an association
between client and WRBX, you can code the cartridge as though it is interacting with
a single client. For example, if you maintain a client-specific counter in your
application context structure, the value of the counter may be different for each
cartridge instance, and will be correctly maintained for each client. In contrast, if your
cartridge uses the request/reply model, such a counter will be global to all cartridge
instances.
Note that in both the request-response and the session models, you can save client
data in the application context structure of the cartridge instance. If you are using the
request-response mode, however, it does not make sense to do so because the next
request from the same client may go to another cartridge instance.
The Exec function for a cartridge of this type typically goes through the following
states as it handles an incoming request:
A transaction can span several calls to the Exec function. To write a cartridge of this
type, you must code your Exec function to determine which of the above states
currently applies. For example, your Exec function might begin a transaction when
the request URI contains the path element “begin” and commit the transaction when
the request URI contains the path element “commit”.
If you write this type of cartridge, your Exec function must call
tx_annotate_path() when handling each request within a transaction. This sends
the current transaction ID to the client in the form of a cookie, specifying a virtual
path corresponding to the next anticipated request in the transaction.
If the client issues a request to your cartridge that does not match a path specified by a
call to tx_annotate_path(), it does not send the transaction ID in the request
header. In this case, the WRB does not resume any transaction context before calling
your Exec function. This allows you to support requests that are independent of any
transaction.
See the WRB Transaction Service API Reference for more information.
The WRB 3.0 API greatly simplifies maintaining client state by introducing sessions.
If your cartridge is session-enabled, you can store client state data locally in your
application context structure. Because each cartridge instance is bound to a client, this
data will remain valid from request to request. If the client issues no requests to the
cartridge for the specified time-out period, the session ends and the cartridge instance
terminates.
When you configure your cartridge (see Configuring Your Cartridge), you can enable
sessions for your cartridge and set the time-out period.
Note that this feature of running cartridges on other machines is available only in the
Advanced version of the Web Application Server; it is not available in the Standard
version.
The ways in which Web cartridges are distributed across machines are determined by
the WRB configuration data on all the machines involved. See the Applications,
Protocols, and Hosts section of the WRB administration pages for more information.
For example, you might want to define a registration cartridge that records personal
data about clients before forwarding their requests to other cartridges.
For more information, see the WRB Inter-Cartridge Exchange Service API Reference.
In addition, the WRB 3.0 API also provides an authentication server that can handle
client authentication for your cartridge, as well as restrict access according to the
client’s IP address or DNS domain. The authentication server can also perform basic
database user authentication for cartridges that access a database. See The Init
Function and WRB_setAuthServer() for more information.
Upgrading from the WRB 2.x API to the WRB 3.0 API
This section outlines how to upgrade a cartridge developed using the WRB 2.x APIs
to take advantage of WRB 3.0 API features.
Instead of this WRB 2.x API call Use this WRB 3.0 API call
WRBGetORACLE_HOME() WRB_getORACLE_HOME()
WRBGetAppConfig() WRB_getAppConfigSection()
WRBGetConfigVal() WRB_getAppConfigVal()
WRBGetURI() WRB_getRequestInfo()
WRBGetURL() WRB_getRequestInfo()
WRBGetLangauge() WRB_getRequestInfo()
WRBGetCharacterEncoding() WRB_getRequestInfo()
WRBGetReqMimeType() WRB_getRequestInfo()
WRBGetUserID() WRB_getRequestInfo()
WRBGetPassword() WRB_getRequestInfo()
WRBGetClientIP() WRB_getRequestInfo()
WRBGetEnvironment() WRB_getEnvironment()
WRBGetEnvironmentVariable() WRB_getEnvironment()
WRBGetDirMap() WRB_getListenerInfo()
WRBGetMimeType() WRB_getListenerInfo()
WRBGetParsedContent() WRB_getParsedContent()
WRBGetNamedEntry() WRB_getParsedContent()
WRBSetAuthorization() WRB_setAuthBasic()
WRBSetAuthorization() WRB_setAuthDigest()
WRBSetAuthorization() WRB_setAuthServer()
WRBClientWrite() WRB_write()
WRBClientRead() WRB_read()
WRBReturnHTTPRedirect() WRB_sendHeader()
• Init - performs one-time setup operations for the cartridge, such as allocating
data structures or other resources that the cartridge needs to handle requests.
• Exec - handles client requests. You must implement this cartridge function.
• Shutdown - frees any resources the cartridge has allocated and prepares the
cartridge to terminate.
• Authorize - determines whether the client issuing a request is authorized to
issue the request.
• Reload - reloads the cartridge configuration data; this function is called
whenever the Web Listener is signalled to reload its configuration data so your
cartridge can reload its configuration data at the same time.
Although you must define an Exec function, implementing the other functions is
optional. Implementing the Reload function, however, is highly recommended for
cartridges that use cartridge configuration data.
You may name your cartridge functions anything you want, but it is a good idea to
incorporate the above strings in the names you choose. For example, you might name
your Init function something like MyApp_Init(). For this reason, this document
uses cartridge function names such as prefix_Init(), where prefix indicates the name
you choose for your cartridge.
8: return 3: dispatch
data request
5: grant 7: return
4: request authorization 6: request data
authorization data
Web Cartridge
• Use the Cartridge Administration page to register your cartridge and define
any cartridge-specific configuration parameters that your cartridge needs.
• If your cartridge uses the sessions mechanism to maintain persistent
associations between clients and WRBXs, you must enable that mechanism in
the WRB administration pages, and also specify the time-out duration, which is
the maximum time your cartridge can be idle before the Dispatcher terminates
it.
• Use the WRB administration pages to define the following for your cartridge:
- An entry in the “Applications and Objects” section
- Virtual directory mappings to allow your cartridge to access any scripts
or data files it uses in the local files system (defined in the Applications
and Directories section)
• Use the Web Listener administration pages to define virtual directory
mappings to allow at least one Listener to access any splash page or other static
documents that accompany your cartridge.
• Use the Authentication Server administration pages to define any
authentication users, groups, or realms that the Authentication Server needs to
perform authentication for your cartridge. If your cartridge handles its own
authentication (see WRB_setAuthBasic() and WRB_setAuthDigest()),
you may omit this step.
Before you can recompile and test each iteration of the cartridge, you must check that
the current version of the cartridge process (the wrbc process) is no longer running.
You can do this using the ps and grep commands:
An efficient way to ensure that the wrbc process is terminated is to code the Exec
callback in your cartridge to return WRB_ERROR instead of WRB_DONE. This causes
the cartridge to terminate when the Exec function returns.
After the wrbc process is terminated, you can recompile the new iteration of the
cartridge. When you submit a request for the cartridge, the WRB should load the new
.so file.
Note that you should not change the .so file while the wrbc process is still running
because the process might be using it.
You can name your entry-point function anything you want. When you configure
your cartridge, you will specify the full path to your cartridge shared library and the
name of your entry-point function. It is a good idea, though, to incorporate the string
“Entry” in your entry-point function name (for example, MyApp_Entry()).
Syntax
WRBReturnCode prefix_Entry(WRBCallbacks *WRBcalls);
Parameters
Return Value
A value of type WRBReturnCode.
Example
See the MyWRBApp_Entry() function in the MyWRBApp sample cartridge.
You can use your Init function to define a data structure that contains data you want
to share among your cartridge functions. The Init function passes back a pointer to the
data structure in the appCtx parameter. The WRB application engine then passes this
pointer when it calls your other cartridge functions.
Note: You must use this method instead of global variables to share data if your cartridge is
to run in a multi-threaded environment. Global variables are not thread-safe in a
multi-threaded environment.
Your Init function can also call the WRB_setAuthServer() function to set up a
client authentication or restriction scheme to be used for the life of the cartridge
instance. If your Init function does this, your Authorize function will never be called.
Alternatively, you can use the WRB administration pages to specify authentication or
restriction schemes for your cartridge. If you do this, any authentication or restriction
schemes that you specify in your Init or Authorize function are ignored.
Syntax
WRBReturnCode prefix_Init(void *WRBCtx, void **appCtx);
Parameters
Return Value
A value of type WRBReturnCode.
Example
See the MyWRBApp_Init() function in the MyWRBApp sample cartridge.
See Also
The Shutdown Function
Your Authorize function must then pass back a boolean value indicating whether the
client is authorized to issue the request. You can use the WRB_getRequestInfo()
function to determine the client’s privileges.
Alternatively, you can call WRB_setAuthServer from your Init function to specify
authentication and/or restriction schemes to be used for the life of the cartridge
instance.
This cartridge function is optional. If you do not implement it, access to your Web
cartridge can be regulated only through the Web Listener and WRB administration
pages.
Syntax
WRBReturnCode prefix_Authorize(void *WRBCtx,
void *appCtx,
boolean *bAuthorized);
Parameters
Return Value
A value of type WRBReturnCode.
See Also
WRB_getRequestInfo(), WRB_setAuthBasic(), WRB_setAuthDigest(),
WRB_setAuthServer()
Syntax
WRBReturnCode prefix_Exec(void *WRBCtx, void *appCtx);
Parameters
Return Value
A value of type WRBReturnCode.
Example
See the MyWRBApp_Exec() function in the MyWRBApp sample cartridge.
Syntax
WRBReturnCode prefix_Shutdown(void *WRBCtx, void *appCtx);
Parameters
Return Value
A value of type WRBReturnCode. Note that returning any value shuts down your
cartridge.
Example
See the MyWRBApp sample function MyWRBApp_Shutdown().
Syntax
WRBReturnCode prefix_Reload(void *WRBCtx, void *appCtx);
Parameters
Return Value
A value of type WRBReturnCode.
Example
See the MyWRBApp sample function MyWRBApp_Reload().
See Also
WRB_getAppConfigSection(), WRB_getAppConfigVal()
version.release.update
This cartridge function is optional; if you do implement it, you must also implement a
Version_Free function.
Syntax
char *prefix_Version();
Parameters
none
Return Values
Your Version cartridge function must return a pointer to a character string identifying
the version number of your cartridge.
Examples
An alpha version of your cartridge might define the following version string:
The first production version of your cartridge might define VERSION as:
The first bug-fixing version of your cartridge might define VERSION as:
The next minor functionality update release of your cartridge might define VERSION
as:
See Also
The Version_Free Function
This cartridge function is optional; you must implement it only if you also implement
a Version function.
Syntax
void prefix_Version_Free();
Parameters
none
Return values
none
See Also
The Version Function
Value Description
WRB_DONE The function completed successfully.
WRB_ERROR An error occurred and the request cannot be completed.
The cartridge does not abort.
WRB_ABORT An error occurred from which the application cannot
recover; you need to terminate the application.
Contents
• Getting Information about the Request
• Getting Information about the Server
• Using Parameter Blocks
• Authenticating the Client
• Creating a Response
• Using Cookies
• Handling Errors
• Analyzing Performance
Several functions return information about the query string; which function you
should use depends on the format of the query string:
• If the request uses the standard GET or POST formats, you should use
WRB_getParsedContent(). This function parses the query string information
and returns it in the form of a parameter block. You can then use the parameter
block functions to get the value of a specific parameter in the query string, or to
walk the whole parameter block to get all the name-value pairs.
HTML forms submit data in the standard GET or POST formats. The query
string is a set of name-value pairs.
• If the request has the “multipart/form” format, use
WRB_getMultipartData(). This format is defined by RFC 1867.
• If the request is not in a standard format, use WRB_read(). This function reads
the specified number of bytes into a buffer, which you can then parse yourself.
The following sample shows how to get POST or GET data submitted from an HTML
form. The HTML source for the form looks like the following:
<html>
<head>
<title>test form</title>
</head>
<body>
<p>buttons
<p>Green <input type=”checkbox” name=”green”>
<p>Blue <input type=”checkbox” name=”blue”>
<p>Black <input type=”checkbox” name=”black”>
</body>
</html>
The action “getFormData” in the FORM tag refers to a cartridge that simply reads and
returns the user’s form selections (that is, it just prints out the names and values of the
selections). The cartridge code is as follows:
#ifndef ORATYPES_ORACLE
# include <oratypes.h>
#endif
#ifndef WRB_ORACLE
# include <wrb.h>
#endif
WRBReturnCode getFormData_init();
WRBReturnCode getFormData_exec();
WRBReturnCode getFormData_shut();
elem=WRB_firstPBElem(WRBCtx,pb,&pos);
for(; elem ; elem = WRB_nextPBElem(WRBCtx, pb, pos) ) {
WRB_printf(WRBCtx,”<p>element name = %s\n”,elem->szParamName);
WRB_printf(WRBCtx,”<p>element val = %s\n\n”,elem->szParamValue);
}
WRB_printf(WRBCtx, “</body></html>”);
return (WRB_DONE);
}
The WRB uses a parameter block to hold these name-value pairs. A parameter block
(which has the type WRBpBlock) is a set of name-value pairs, where each name-value
pair is encoded in the WRBpBlockElem struct type. This parameter block element
struct is defined as:
dvoid *pNVdata;
} WRBpBlockElem;
WRBpBlock
Several WRB API functions provide data in the WRBpBlockElem type, which you can
pass to the parameter block functions. For example, the following code calls
WRB_getParsedContent() to get a parameter block that contains name-value pairs
found in the query string, and then calls WRB_findPBElemVal() to get the value of
a parameter called “lastname”:
WRBpBlock *qstring;
text *lname;
/* gets the query string information and places it in qstring */
WRB_getParsedContent(ctx, qstring);
/* gets the value of the “lastname” parameter in the
qstring parameter block */
lname = WRB_findPBElemVal(ctx, qstring, (text *)”lastname”,
-1);
WRB API also provides functions that let you walk a parameter block. To do this, you
call WRB_firstPBElem() to get the first element in the parameter block, and then call
WRB_nextPBElem() to get each subsequent element. WRB_nextPBElem() returns
NULL when there are no more elements.
WRBpBlock hPBlock;
WAPIReturnCode ret;
WRBpBlockElem *elem;
dvoid *pos;
/* Get the headers and save them in hPBlock */
ret = WRB_recvHeaders(ctx, &hPBlock);
if (ret != WRB_SUCCESS) {
return (WRB_ERROR);
}
WRB_printf(ctx, “<dl>”); /* start an HTML definition list. */
/* walk the parameter block */
for (elem = WRB_firstPBElem(ctx, hPBlock, &pos);
elem; elem = WRB_nextPBElem(ctx, hPBlock, pos)) {
/* return the parameter name and value to the user */
The following table lists the functions that let you manipulate parameter blocks:
Function Description
WRB_createPBlock() Creates a parameter block
WRB_addPBElem() Adds an element to a parameter block
WRB_copyPBlock() Copies a parameter block
WRB_delPBElem() Deletes an element from a parameter block
WRB_destroyPBlock() Destroys a parameter block
WRB_findPBElem() Finds an element by name in a parameter block
WRB_walkPBlock() Finds an element by position in a parameter block
WRB_numPBElem() Returns the number of elements in the parameter
block
WRB_firstPBElem() Returns the first element in a parameter block
WRB_nextPBElem() Returns the next element in a parameter block
WRB_findPBElemVal() Returns the value of a parameter in a parameter
block
The following table lists the functions that enable you to authenticate the client:
Function Description
WRB_setAuthBasic() Create a new basic authentication realm
WRB_setAuthDigest() Create a new digest authentication realm
WRB_setAuthServer() Use the authentication server for
authentication
WRB_getClientCert() Get an SSL certificate from the client
Creating a Response
WRB API provides functions that enable you to generate HTTP headers and HTML
pages dynamically.
Using Cookies
WRB API provides the WRB_getCookies() and WRB_setCookies() functions,
which enable you to set and get cookie data. WRB_setCookies() must be called
when you are setting HTTP header information for your response, that is, you call it
before you send the header information with WRB_sendHeader().
Handling Errors
WRB API provides the WRB_getPreviousError() function which lets you get the
most recent error that was logged in the log file. You can get the error text for the most
recent error and display it to the user.
Analyzing Performance
WRB API provides the WRB_timestamp() function, which writes an entry in the log
file when this function is executed.
MyWRBApp is a simple electronic commerce cartridge that illustrates how to use the
WRB API to do these programming tasks:
The MyWRBApp_Entry() function sets up this function dispatch table for the
MyWRBApp cartridge.
After the entry-point function returns, if the cartridge has defined an Init cartridge
function, the WRB application engine calls the Init function to perform any other one-
time setup that the cartridge needs. The Init function may allocate an application
context structure of any type and pass a pointer to it back to the WRB application
engine for that WRBX. The WRB application engine subsequently passes this pointer
to every cartridge function that runs in that WRBX.
MyWRBApp illustrates one way to do this, using per-user database documents that
are shared among WRBXs. The newUser(), getUserData(), and editUserData()
functions, and the functions that they call, manipulate these documents.
The MyWRBApp cartridge must run with sessions enabled, because it stored client
data in it application context structure (see The myappctx Structure). When a user
submits the MyWRBApp catalog form to add items to an order, the MyWRBApp
cartridge keeps track of the ordered items in the myappctx structure.
The user may then leave and return to the catalog page many times, adding or
removing items from the order, and because the Dispatcher maintains the association
between client and WRBX, the myappctx structure correctly keeps track of the order.
When the user finally confirms the order, the Dispatcher signals the browser to delete
the unique identifier cookie from its local storage.
#ifndef ORATYPES_ORACLE
#include <oratypes.h>
#endif
#ifndef WRB_ORACLE
#include <wrb.h>
#endif
#ifndef CONTENT_ORACLE
#include <content.h>
#endif
#include <string.h>
#include <sys/types.h> /* <sys\type> for Windows NT */
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
/*
* application context--set up by Init function and subsequently passed
* to each cartridge function by the WRB application engine
*/
typedef struct myappctx {
dvoid *hRepository; /* handle to our CMS content repository */
orderitem *items; /* pointer to ordered items array */
int numitems; /* number of orders currently in array */
text *state; /* our home state, read from configuration data */
double taxpct; /* tax in our area, read from configuration data */
} myappctx;
/*
* MyWRBApp cartridge functions
*/
WRBReturnCode
MyWRBApp_Entry(WRBCallbacks *WRBCalls);
WRBReturnCode
MyWRBApp_Init(void *WRBCtx, void **appCtx);
WRBReturnCode
MyWRBApp_Shutdown(void *WRBCtx, void *appCtx);
WRBReturnCode
MyWRBApp_Authorize(void *WRBCtx, void *appCtx, boolean *bAuthorized);
WRBReturnCode
MyWRBApp_Exec(void *WRBCtx, void *appCtx);
WRBReturnCode
MyWRBApp_Reload(void *WRBCtx, void *appCtx);
#ifdef DEBUG
static char debug[1024];
#endif
/*
* forward declarations
*/
WRBReturnCode newUser(myappctx *ctx, dvoid *WRBCtx);
MyWRBApp_Entry()
MyWRBApp_Entry() sets up the provided WRBCallbacks dispatch table so the WRB
application engine can call MyWRBApp’s cartridge functions.
WRBReturnCode
MyWRBApp_Entry(WRBCallbacks *WRBCalls)
{
WRBCalls->init_WRBCallback = MyWRBApp_Init;
WRBCalls->authorize_WRBCallback = MyWRBApp_Authorize;
WRBCalls->exec_WRBCallback = MyWRBApp_Exec;
WRBCalls->shut_WRBCallback = MyWRBApp_Shutdown;
return (WRB_DONE);
}
MyWRBApp_Init()
MyWBApp_Init() sets up the cartridge to handle client requests. It allocates the
myappctx structure and the ordered items array, and opens a connection to the content
repository where it will store the catalog and user data files. MyWRBApp_Init() then
completes initialization of the context structure and passes it back to the WRB
application engine when it returns.
WRBReturnCode
MyWRBApp_Init(dvoid *WRBCtx, dvoid **appCtx)
{
myappctx *ctx;
WRBReturnCode ret;
return (WRB_DONE);
}
MyWRBApp_Shutdown()
MyWRBApp_Shutdown() frees resources used by the cartridge in preparation for
termination. It saves the data file to the file system, and unmaps and closes the data
file. It then frees the ordered items array and the application context structure before
returning.
WRBReturnCode
MyWRBApp_Shutdown(dvoid *WRBCtx, dvoid *appCtx)
{
myappctx *ctx = (myappctx *)appCtx;
return (WRB_DONE);
}
MyWRBApp_Authorize()
The WRB application engine calls MyWRBApp_Authorize() when it receives a request
directed to MyWRBApp. MyWRBApp_Authorize() authenticates the client issuing the
request.
MyWRBApp does not require any special authorization to register a new a username,
so if the request is “newuser,” MyWRBApp_Authorize() grants authorization and
returns immediately.
RBReturnCode
MyWRBApp_Authorize(dvoid *WRBCtx, dvoid *appCtx, boolean *bAuthorized)
{
text *URL, *req, *user, *password, *storedPassword;
myappctx *ctx = (myappctx *)appCtx;
int cmp;
/* get the password provided by the client and copy to local memory */
password = WRB_getRequestInfo(WRBCtx, WRBR_PASSWORD);
password = (text *)strdup((char *)password); /* XXX still needed? */
if (!cmp) {
*bAuthorized = TRUE;
}
else {
*bAuthorized = FALSE;
#ifdef DEBUG
sprintf(debug,
"MyWRBApp_Authorize: user %s gave an incorrect password: %s",
user, password);
WRBLogMessage(WRBCtx, debug, 1);
#endif
}
return(WRB_DONE);
}
MyWRBApp_Exec()
The WRB application engine calls MyWRBApp_Exec() to handle a request when
MyWRBApp_Authorize() has indicated that the client is authorized. MyWRBApp_Exec()
reads the URL to determine the request. MyWRBApp supports the following requests:
#ifdef DEBUG
sprintf(debug, "MyWRBApp_Exec: request is %s", req);
WRBLogMessage(WRBCtx, debug, 1);
#endif
return(WRB_DONE);
}
WRBReturnCode
MyWRBApp_Reload(dvoid* WRBCtx, dvoid *appCtx)
{
myappctx *ctx = (myappctx*)appCtx;
text *tax;
text *cp;
if (tax) {
/* remove percent sign from tax, if any */
cp = (text *)strchr((char *)tax, '%');
if (cp) {
cp = '\0';
}
ctx->taxpct = atof((char *)tax);
}
else {
ctx->taxpct = (double)0;
}
return (WRB_DONE);
}
newUser()
MyWRBApp_Exec() calls newUser() to handle “newuser” requests. Its primary task is
to process the data from the newuser.html form that the client has submitted (see the
$ORACLE_HOME/ows/3.0/sample/wrbsdk/mywrbapp (UNIX) or
%ORACLE_HOME%\ows\3.0\wrbsdk\mywrbapp (NT) directory on your Web
Application Server machine).
newUser() uses WRB API function WRB_getParsedContent() to parse the CGI data
from the form. The function passes back an array of WRBEntry structures, each of
which encodes the name and value of an input field on the form. newUser() then uses
the WRB API function WRB_findPBElemVal() to extract the values of specific input
fields.
WRBReturnCode
newUser(myappctx *ctx, dvoid *WRBCtx)
{
text *user, *password, *confirm, *cp;
dvoid *hInfoFile;
WRBReturnCode ret;
WRBpBlock hPBlock;
WRBpBlockElem *elem;
sb4 numelems;
text wbuf[1024];
int len;
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
return (ret);
}
/* done--go to catalog */
WRB_destroyPBlock(WRBCtx, hPBlock);
getUserData()
MyWRBApp_Exec() calls getUserData() to handle “getuserdata” requests. Its task is to
extract from the data file the username and password of the currently authenticated
user, and call formatUserData() to generate and send to the client an HTML form
containing the user’s registration data. getUserData() uses the WRB API function
WRBGetUserID() to identify the currently authenticated user.
return (ret);
}
editUserData()
When the user edits and submits the HTML form generated by getUserData(), the
form’s action specifies the “edituserdata” request. MyWRBApp_Exec() then calls
editUserData() to handle this request.
WRBReturnCode
editUserData(myappctx *ctx, dvoid *WRBCtx)
{
text *user, *curUser, *password, *confirm;
text wbuf[1024];
int len;
dvoid *hInfoFile;
WRBpBlock hPBlock;
WRBpBlockElem *elem;
sb4 numelems;
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
/*
* has the user changed his/her username?
* if so, and the new name is not in use, rehash datablock
*/
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
/* destroy old info file before calling storeInfo to create new one */
WRB_CNTdestroyDocument(WRBCtx, ctx->hRepository, (text *)curUser);
#ifdef DEBUG
sprintf(debug,
"editUserData: old username: %s\n\tnew username %s",
curUser, user);
WRBLogMessage(WRBCtx, debug, 1);
#endif
}
/* done--go to catalog */
WRB_destroyPBlock(WRBCtx, hPBlock);
return(getCatalog(ctx, WRBCtx));
}
getCatalog()
MyWRBApp_Exec() calls getCatalog() to handle “getcatalog” requests. Its main task is
to read the catalog file (catalog.txt), apply HTML formatting to it, and send it to the
client as an editable HTML form.
For each catalog item, getCatalog() searches the catalog file for that item’s part
number; if it finds the item, it uses its value to set the default value of the input field in
the output form. This value represents the quantity of the item ordered.
WRBReturnCode
getCatalog(myappctx *ctx, dvoid *WRBCtx)
{
dvoid *hCatFile;
/* open catalog */
hCatFile = WRB_CNTopenDocument(WRBCtx, ctx->hRepository,
(text *)"catalog", WRBCS_OPEN | WRBCS_READ);
if (!hCatFile) {
#ifdef DEBUG
sprintf(debug, "getCatalog: failed to open catalog: %s",
strerror(errno));
WRBLogMessage(WRBCtx, debug, 1);
#endif
return (WRB_ABORT);
}
WRB_printf(WRBCtx,
(text *)"<HTML><HEAD><TITLE>Hot Goods Catalog</TITLE></HEAD>\n");
WRB_printf(WRBCtx, (text *)"<BODY BGCOLOR=\"FFFFFF\">\n");
WRB_printf(WRBCtx, (text *)"<H1>Hot Goods Catalog</H1>\n");
WRB_printf(WRBCtx,
(text *)"<FORM ACTION=\"/mywrbapp/bin/placeorder\" METHOD=\"POST\">\n");
/*
* Loop through the catalog generating HTML for each line--
* for each part number listed in the catalog, check the
* ordered items to see if the user has already entered an order quantity
* for the item
*/
while (myfgets(buf, 1024, hCatFile, WRBCtx)) {
/* write the description line to the client */
WRB_printf(WRBCtx, (text *)"<P>");
WRB_printf(WRBCtx, buf);
WRB_printf(WRBCtx, (text *)"</P>\n<P>");
/* get part number line and write it out without the newline */
myfgets(buf, 1024, hCatFile, WRBCtx);
WRB_printf(WRBCtx, buf);
items = ctx->items;
item = 0;
*qp = '\0';
/*
* complete the HTML line with an input box and set its value to
* the quantity stored in the ordered items array (if any)
*/
WRB_printf(WRBCtx,
(text *)" Order quantity: <INPUT TYPE=\"text\" NAME=\"%s\" ", part);
WRB_printf(WRBCtx, (text *)"SIZE=\"4\" VALUE=\"%s\"></P>\n", qty);
}
WRB_CNTcloseDocument(WRBCtx, hCatFile);
return (WRB_DONE);
}
placeOrder()
When the user edits and submits the HTML form generated by getCatalog(), the
form’s action specifies the “placeorder” request. MyWRBApp_Exec() then calls
placeOrder() to handle this request. Its main task is to generate an HTML form that
summarizes the items the client has ordered, and asking the client for confirmation.
To determine the items ordered, placeOrder() first parses the cookie data, and then
the data from the form generated by getCatalog(). In the case of a discrepancy
between the cookie data and form data, placeOrder() uses the form data. This allows
a user to change the quantity on an order item or delete an item from the order entirely
before submitting the “placeorder” request.
WRBReturnCode
placeOrder(myappctx *ctx, dvoid *WRBCtx)
{
WRBReturnCode ret;
WRBpBlock hPBlock;
WRBpBlockElem *elem;
sb4 numelems;
int item, num;
text wbuf[1024];
int len;
orderitem *items;
item = 0;
items = ctx->items;
#ifdef DEBUG
sprintf(debug, "placeOrder: numitems: %d", ctx->numitems);
WRBLogMessage(WRBCtx, debug, 1);
#endif
WRB_printf(WRBCtx,
(text *)"<HTML><HEAD><TITLE>Order Form</TITLE></HEAD>\n");
WRB_printf(WRBCtx, (text *)"<BODY BGCOLOR=\"FFFFFF\">\n");
WRB_printf(WRBCtx, (text *)"<H1>Placing an Order</H1>\n");
WRB_printf(WRBCtx,
(text *)"<P>These are the items and the quantities you have selected. ");
WRB_printf(WRBCtx,
(text *)"To change the quantity of an item you want to order, ");
WRB_printf(WRBCtx,
(text *)"just change the value in the quantity box for that item. ");
WRB_printf(WRBCtx,
(text *)"If you decide you don't want to order an item after all, ");
WRB_printf(WRBCtx,
WRB_printf(WRBCtx,
(text *)"<INPUT TYPE=\"submit\" VALUE=\"Confirm Order\">\n");
WRB_printf(WRBCtx, (text *)"</FORM>\n</BODY>\n</HTML>\n");
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
confirmOrder()
When the user edits and submits the HTML form generated by placeOrder(), the
form’s action specifies the “confirm” request. MyWRBApp_Exec() then calls
confirmOrder() to handle this request. Its main task is to generate an invoice
summarizing the client’s order. It also signals the client browser to delete the cookies
associated with the order.
WRBReturnCode
confirmOrder(myappctx *ctx, dvoid *WRBCtx)
{
WRBReturnCode ret;
WRBpBlock hPBlock;
WRBpBlockElem *elem;
sb4 numelems;
int item, num;
text wbuf[1024];
int len;
text *cp, *tp;
text part[PARTNUMLEN + 1];
orderitem *items;
/* begin response */
WRB_printf(WRBCtx, (text *)"Content-type: text/html\n");
/* write out the order summary and total by setting invoice to TRUE */
ret = formatOrder(TRUE, ctx, WRBCtx);
if (ret != WRB_DONE) {
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_ERROR);
}
WRB_printf(WRBCtx,
(text *)"<P><A HREF=\"/mywrbapp/bin/getcatalog\">Return to the catalog");
WRB_printf(WRBCtx, (text *)"</A>.</P>\n</BODY>\n</HTML>\n");
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
formatUserData()
getUserData() calls formatUserData() to generate and send to the client an HTML
form containing the registration data for the user specified by the data block data.
WRBReturnCode
formatUserData(text *user, myappctx *ctx, void *WRBCtx)
{
dvoid *hInfoFile;
text *field;
#ifdef DEBUG
WRBLogMessage(WRBCtx, "formatUserData: opening infofile", 0);
#endif
hInfoFile = WRB_CNTopenDocument(WRBCtx, ctx->hRepository, user,
WRBCS_OPEN | WRBCS_READ);
if (!hInfoFile) {
return (WRB_ERROR);
}
/*
* write out data form
*/
#ifdef DEBUG
WRBLogMessage(WRBCtx, "formatUserData: starting client writes", 0);
#endif
WRB_printf(WRBCtx,
(text *)"<HTML>\n<HEAD><TITLE>Registration Form</TITLE></HEAD>\n");
/* username */
field = getInfoField(NULL, hInfoFile, USERNAME, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>Username: <INPUT TYPE=\"text\" NAME=\"username\" ");
WRB_printf(WRBCtx,
(text *)"VALUE=\"%s\" MAXLENGTH=\"10\" SIZE=\"10\"></P>\n", field);
/* password */
field = getInfoField(NULL, hInfoFile, PASSWORD, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>Password: <INPUT TYPE=\"password\" NAME=\"password\" ");
WRB_printf(WRBCtx, (text *)"VALUE=\"%s\" MAXLENGTH=\"10\" SIZE=\"10\">\n",
field);
/* confirm password */
WRB_printf(WRBCtx,
(text *)" Confirm Password: <INPUT TYPE=\"password\" NAME=\"confirm\" ");
WRB_printf(WRBCtx,
(text *)"VALUE=\"%s\" MAXLENGTH=\"10\" SIZE=\"10\"></P>\n", field);
/* fullname */
field = getInfoField(NULL, hInfoFile, FULLNAME, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>Full Name: <INPUT TYPE=\"text\" NAME=\"fullname\" ", field);
/* address */
field = getInfoField(NULL, hInfoFile, ADDRESS, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>Street Address: <INPUT TYPE=\"text\" NAME=\"address\" ");
WRB_printf(WRBCtx, (text *)"VALUE=\"%s\"></P>\n", field);
/* city */
field = getInfoField(NULL, hInfoFile, CITY, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>City: <INPUT TYPE=\"text\" NAME=\"city\" ");
WRB_printf(WRBCtx, (text *)"VALUE=\"%s\"></P>\n", field);
/* state */
field = getInfoField(NULL, hInfoFile, STATE, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>State: <INPUT TYPE=\"text\" NAME=\"state\" ");
WRB_printf(WRBCtx,
(text *)"VALUE=\"%s\" MAXLENGTH=\"2\" SIZE=\"2\"></P>\n", field);
/* zip */
field = getInfoField(NULL, hInfoFile, ZIP, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>Zip: <INPUT TYPE=\"text\" NAME=\"zip\" ");
WRB_printf(WRBCtx, (text *)"VALUE=\"%s\"></P>\n", field);
/* country */
field = getInfoField(NULL, hInfoFile, COUNTRY, ctx, WRBCtx);
WRB_printf(WRBCtx,
(text *)"<P>Country: <INPUT TYPE=\"text\" NAME=\"country\" ");
WRB_printf(WRBCtx, (text *)"VALUE=\"%s\"></P>\n", field);
/* email */
#ifdef DEBUG
WRBLogMessage(WRBCtx, "formatUserData: finished client writes", 0);
#endif
WRB_CNTcloseDocument(WRBCtx, hInfoFile);
return (WRB_DONE);
}
userDataError()
newUser() and editUserData() calls userDataError() to generate an HTML error
page using the text specified by message. The URL parameter specifies the registration
form to which to provide a link.
void
userDataError(const text *message, const text *URL, myappctx* ctx, void *WRBCtx)
{
text wbuf[1024];
int len;
return;
}
storeInfo()
newUser() and editUserData() call storeInfo() to parse all registration form data
for a user (except username and password, which are hashed in the data file) and store
it in an ASCII file on the host file system.
WRBReturnCode
storeInfo(text *user, myappctx *ctx, void *WRBCtx)
{
dvoid *hInfoFile;
text buf[256];
text *cp;
WRBpBlock hPBlock;
WRBpBlockElem *elem;
sb4 numelems;
WRB_CNTcloseDocument(WRBCtx, hInfoFile);
WRB_destroyPBlock(WRBCtx, hPBlock);
return (WRB_DONE);
}
formatOrder()
placeOrder() and confirmOrder()call formatOrder() to format the client order
encapsulated in the ctx structure in HTML format and send it to the client.
If invoice is TRUE, formatOrder() outputs a non-editable HTML page and prints price
totals. Otherwise, it outputs an editable HTML form with <INPUT> fields. formatOrder()
does not output a Content-type header, an HTML header, or an HTML trailer; the caller
is responsible for outputting that information.
WRBReturnCode
formatOrder(const boolean invoice, myappctx *ctx, void *WRBCtx)
{
/* open catalog */
hCatFile = WRB_CNTopenDocument(WRBCtx, ctx->hRepository, (text *)"catalog",
WRBCS_OPEN | WRBCS_READ);
if (!hCatFile) {
#ifdef DEBUG
WRBLogMessage(WRBCtx, "formatOrder: failed to open catalog", 0);
#endif
return (WRB_ABORT);
}
/*
* because both the items array and the catalog file are sorted by
* part number, loop through without seeking backward
*/
items = ctx->items;
while ((item < ctx->numitems)) {
if ((items[item].qty[0] == '\0') || (items[item].qty[0] == '0')) {
/* skip empty quantities */
item++;
continue;
}
if (invoice) {
/* calculate and print price, add to subtotal */
lp = (text *)strchr((char *)lbuf, '$');
lp++;
itemprice = atof((char *)lp);
quantity = atof((char *)items[item].qty);
WRB_printf(WRBCtx,
(text *)" Quantity: %s @ $%.2f = $%.2f</P>\n",
items[item].qty, itemprice, itemprice * quantity);
if (invoice) {
if (taxable(WRB_getRequestInfo(WRBCtx, WRBR_USER), ctx,
WRBCtx)) {
/* print subtotal */
WRB_printf(WRBCtx, (text *)"<P>Subtotal: $%.2f</P>\n", total);
WRB_CNTcloseDocument(WRBCtx, hCatFile);
return (WRB_DONE);
}
taxable()
taxable() uses the client’s registration data and the cartridge configuration
parameters to determine whether the client lives in our home state, and hence should
be charged sales tax.
boolean
taxable(text *user, myappctx *ctx, void *WRBCtx)
{
text *state;
itemcmp()
placeOrder() passes a pointer to itemcmp() to the qsort(3) library function to use in
sorting the orderitems array that encapsulates a client’s order.
int
itemcmp(const void* item1, const void* item2)
{
return(strcmp((char *)((orderitem *)item1)->partnum,
(char *)((orderitem *)item2)->partnum));
}
getInfoField()
getInfoField() returns the value of a specified info file field. The info file is specified
either by user name, or by a pointer to an open info file.
text *
getInfoField(text *user, dvoid *hInfoFile, text *field, myappctx *ctx,
dvoid *WRBCtx)
{
text buf[1024];
text *cp = NULL;
if (!hInfoFile) {
hInfoFile = WRB_CNTopenDocument(WRBCtx, ctx->hRepository, user,
WRBCS_OPEN & WRBCS_READ);
}
if (!hInfoFile) {
return (NULL);
}
WRB_CNTcloseDocument(WRBCtx, hInfoFile);
return ((text *)strdup((char *)cp));
}
text *
myfgets(text *buf, int size, dvoid *hFile, dvoid *WRBCtx)
{
text byte[1];
int i = 0;
if (i) {
return (buf);
}
return (NULL);
}
uploadCatalog()
uploadCatalog() creates the catalog document in the content repository from data
stored in the local file system. This is just a convenience to set up the database content
for you the first time you try out MyWRBApp.
WRBReturnCode
uploadCatalog(myappctx *ctx, dvoid *WRBCtx)
{
dvoid *hCatFile;
FILE *file;
text *ohome;
WAPIReturnCode ret;
text buf[1024];
ohome = WRB_getORACLE_HOME(WRBCtx);
if (!ohome) {
/* ORACLE_HOME is not set */
return (WRB_ABORT);
}
if (!file) {
/* catalog file is not present */
return (WRB_ABORT);
}
WRB_CNTcloseDocument(WRBCtx, hCatFile);
fclose(file);
return (WRB_DONE);
}
The Document Server cartridge is a custom cartridge that uses the Content Service
APIs to manage documents in a database repository. It also uses the ICX
(Intercartridge Service) APIs to retrieve documents from the Web.
Contents
• Features of the Document Server Cartridge
• Cartridge Registration
• Cartridge Invocation and Flow Process
• The Callback Functions
• The Upload Page Function
• The Upload Document (Local and Remote) Function
• The Download Document Function
• The Display Attributes Function
• The Set Attributes Function
• The List Documents Function
• Complete Source for the Document Server Cartridge
Users interact with the cartridge through HTML forms. The contents of these forms are
generated by the code in the cartridge.
Main Screen
When the user first invokes the cartridge, the main screen appears (Figure 5-1).
The main screen is a frameset: the left frame shows the contents of the repository, and
the right frame is a splash screen. When the user selects an operation (download a
document for viewing, upload a document, set attributes, or get attributes), the right
frame changes to display the appropriate page.
Downloading Documents
To download a document from the repository, the user clicks the document from the
“Repository listing” on the left frame. The selected document is fetched and displayed
in the right frame.
To view the attributes associated with a document, the user clicks the red circle to the
left of the document’s name. The right frame displays a page that looks like the
following:
Uploading Documents
To upload a document to the repository, the user clicks Upload to view the Upload
page. The top part of the page is for a “local upload”, where the user uploads a
document from his file system. The bottom part of the page is for a “remote upload”,
Parameter Value
The virtual path can be changed in the registration of the cartridge without affecting
the cartridge’s code, because it is not hardcoded in the code. Instead, the code calls
WRB_getRequestInfo(WRBctx, WRBR_VIRTUALPATH) to get the virtual path.
http://machine:port/tcont
When the cartridge starts up for the first time, it executes the Entry-Point function and
the Init function. These functions define the callback functions and connect to the
repository. See The Callback Functions for details.
The cartridge then handles the request in the Exec function, which checks for cartridge-
defined keywords such as “upload” and “download” in the URL. In this case of the
first request, the URL does not contain any keywords and the default case in the
switch statement is executed. The default case calls content_frameset(), which
creates the two pages in the frameset. The page in the left frame is generated by
content_list(), and the page in the right frame is generated by
content_main().
• A red circle that is a link and the name of the document (which is also a link) for
each document in the list. When a user clicks the red circle, the cartridge displays
the attributes of the document. When the user clicks the document name, the
document is downloaded from the repository.
• An “Update” button to display the Upload Page.
To submit requests to the cartridge, the user clicks on links in the generated HTML
pages; the user does not manually type in the URL.
From the main page, the user can View/Set On this page, the user can
click the red circle to display the Attributes specify new attributes and
view/set attributes page. This page is Page values for a document and
generated by content_attrib(). click the Set Attrib button,
which invokes
content_set_attrib().
typedef struct
{
dvoid *hRepository;
dvoid *hDoc;
text *szProxy;
text *szNoProxyOn;
text *szVirtualPath;
} content_struct;
cs = (content_struct *)malloc(sizeof(content_struct));
if (!cs) {
content_debug(“Error in malloc exiting\n”);
return WRB_ABORT;
}
if (!(cs->hRepository = WRB_CNTopenRepository(WRBCtx,
NULL, NULL, (text *)“WEBSYS”))) {
content_debug(“Error in open repository. \
Refer to wrb.log for additional info\n”);
return WRB_ABORT;
}
*clientcxp = cs;
return (WRB_DONE);
}
The Init function allocates an application context structure (cs) that the cartridge uses
to keep track of the repository and current document.
if (!(cs->szVirtualPath = WRB_getRequestInfo(WRBCtx,
WRBR_VIRTUALPATH)))
cs->szVirtualPath = (text *)”/tcont”;
switch (uritype) {
case CONTENT_UPLOAD:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
WRB_printf(WRBCtx, “<HTML>\n”);
WRB_printf(WRBCtx, “<BODY bgcolor=\”black\” text=\”yellow\”\
link=\”yellow\” vlink=\”green\” >”);
if (content_upload(WRBCtx, cs, FALSE))
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Document successfully uploaded\n”);
}
case CONTENT_ICX:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
if (content_upload(WRBCtx, cs, TRUE))
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Document successfully uploaded\n”);
}
else
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Error in uploading\n”);
}
break;
case CONTENT_DOWNLOAD:
if (!content_download(WRBCtx, cs))
WRB_printf(WRBCtx, “Error in downloadinf\n”);
break;
case CONTENT_LIST:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
content_list(WRBCtx, cs);
break;
case CONTENT_MAIN:
WRB_printf(WRBCtx, “Content-type:text/html\n\n”);
content_main(WRBCtx, cs);
break;
case CONTENT_UPLOAD_PAGE:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
content_upload_page(WRBCtx, cs);
break;
case CONTENT_ATTRIB:
content_attrib(WRBCtx, cs);
break;
case CONTENT_SETATTRIB:
content_set_attrib(WRBCtx, cs);
case CONTENT_DELETE:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
WRB_printf(WRBCtx, “<HTML>\n”);
WRB_printf(WRBCtx, “<BODY bgcolor=\”black\” text=\”yellow\”\
link=\”yellow\” vlink=\”green\” >”);
content_delete(WRBCtx, cs);
content_list(WRBCtx, cs);
break;
default:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
content_frameset(WRBCtx, cs);
break;
}
return (WRB_DONE);
}
return 0;
}
WRB_CNTcloseRepository(WRBCtx, cs->hRepository);
return (WRB_DONE);
}
The Shutdown function closes the repository and frees the client context.
WRB_printf(WRBCtx, “<BR><BR>\n \
<h2> Upload documents thru ICX</h2>\n \
<form method=POST action=%s/tcont_upload_icx target=\”leftnav\”>\n\
Enter Document name to be stored in the repository \
<input type=text name=file size=25><p>\n \
(Document name should begin with a \”/\” )<p> \
Enter the URL for the document to upload: \
<input type=text name=url size=30><p>\n \
<INPUT TYPE=SUBMIT VALUE=\”Upload File\”>\n \
<INPUT TYPE=RESET VALUE=Reset>\n \
</form>\n”, cs->szVirtualPath);
return TRUE;
}
After calling content_upload(), the Exec function updates the list of documents
shown in the browser by calling the content_list() function.
if (icx)
{
if (WRB_getParsedContent(WRBCtx, &content) != WRB_SUCCESS)
{
WRB_printf(WRBCtx, “Error in parsing querystring\n”);
return FALSE;
}
WRB_ICXsetProxy(WRBCtx, cs->szProxy);
WRB_ICXsetNoProxy(WRBCtx, cs->szNoProxyOn);
if (!file)
{
WRB_printf(WRBCtx, “Filename not specified\n”);
return FALSE;
}
WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
cs->hDoc = NULL;
return TRUE;
}
extn = content_extension(file);
mimetypes = WRB_getListenerInfo(WRBCtx, WRBL_MIMETYPES);
if (!(mimetype = WRB_findPBElemVal(WRBCtx, mimetypes, extn, -1)))
mimetype = (text *)”text/plain”;
WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
WRB_destroyPBlock(WRBCtx, content);
cs->hDoc = NULL;
return TRUE;
}
attributes = WRB_createPBlock(WRBCtx);
if (WRB_CNTgetAttributes(WRBCtx, cs->hDoc, attributes) < 0)
goto exit_attrib;
WRB_printf(WRBCtx, “</PRE>\n”);
WRB_printf(WRBCtx, “<BR><BR><P><h3> Set Document Attributes for
%s</h3>\n”, file);
WRB_printf(WRBCtx,
“<FORM METHOD=GET action=%s/tcont_set_attrib> \n\
<input type=hidden name=file value=%s> \n\
Name: <input type=text name=name1 size=20> <br>\n\
Value: <input type=text name=value1 size=30> <p> \n\
Name: <input type=text name=name2 size=20> <br>\n\
Value: <input type=text name=value2 size=30> <p> \n\
Name: <input type=text name=name3 size=20> <br>\n\
Value: <input type=text name=value3 size=30> <p>\n\
<INPUT TYPE=SUBMIT VALUE=\”Set Attrib\”> \n\
<INPUT TYPE=RESET VALUE=Reset> \n\
</FORM>\n”, cs->szVirtualPath, file);
WRB_printf(WRBCtx, “</HTML>\n”);
WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
cs->hDoc = NULL;
WRB_destroyPBlock(WRBCtx, content);
WRB_destroyPBlock(WRBCtx, attributes);
return TRUE;
exit_attrib:
WRB_printf(WRBCtx, “Error in listing attributes\n”);
WRB_printf(WRBCtx, “</HTML>\n”);
return FALSE;
}
if (!(attributes = WRB_createPBlock(WRBCtx)))
goto exit_set_attrib;
rval = TRUE;
exit_set_attrib:
if (cs->hDoc) WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
return rval;
}
if (!WRBCtx || !cs)
return FALSE;
exit_list:
WRB_printf(WRBCtx, “<FORM METHOD = GET
ACTION=\”%s/tcont_upload_page\” \
target = \”main\”>\n\
<INPUT TYPE=SUBMIT VALUE=Upload>\n\
</FORM>”, cs->szVirtualPath);
return TRUE;
}
#ifndef ORATYPES_ORACLE
# include <oratypes.h>
#endif
#ifndef WRB_ORACLE
# include <wrb.h>
#endif
#ifndef CONTENT_ORACLE
# include <content.h>
#endif
#ifndef ICX_ORACLE
# include <icx.h>
#endif
typedef struct
{
dvoid *hRepository;
dvoid *hDoc;
text *szProxy;
text *szNoProxyOn;
text *szVirtualPath;
} content_struct;
va_start(vlist, fmt);
vfprintf(stderr, fmt, vlist);
va_end(vlist);
}
cs = (content_struct *)malloc(sizeof(content_struct));
if (!cs)
{
content_debug(“Error in malloc exiting\n”);
return WRB_ABORT;
}
if (!(cs->hRepository =
WRB_CNTopenRepository(WRBCtx, NULL, NULL, (text *)”WEBSYS”)))
{
content_debug(“Error in open repository. \
Refer to wrb.log for additional info\n”);
return WRB_ABORT;
}
*clientcxp = cs;
return (WRB_DONE);
}
return 0;
}
switch (uritype)
{
case CONTENT_UPLOAD:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
WRB_printf(WRBCtx, “<HTML>\n”);
WRB_printf(WRBCtx, “<BODY bgcolor=\”black\” text=\”yellow\”\
link=\”yellow\” vlink=\”green\” >”);
if (content_upload(WRBCtx, cs, FALSE))
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Document successfully uploaded\n”);
}
else
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Error in uploading\n”);
}
WRB_printf(WRBCtx, “</HTML>\n”);
case CONTENT_ICX:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
if (content_upload(WRBCtx, cs, TRUE))
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Document successfully uploaded\n”);
}
else
{
content_list(WRBCtx, cs);
WRB_printf(WRBCtx, “<BR>Error in uploading\n”);
}
break;
case CONTENT_DOWNLOAD:
if (!content_download(WRBCtx, cs))
WRB_printf(WRBCtx, “Error in downloadinf\n”);
break;
case CONTENT_LIST:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
content_list(WRBCtx, cs);
break;
case CONTENT_MAIN:
WRB_printf(WRBCtx, “Content-type:text/html\n\n”);
content_main(WRBCtx, cs);
break;
case CONTENT_UPLOAD_PAGE:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
content_upload_page(WRBCtx, cs);
break;
case CONTENT_ATTRIB:
content_attrib(WRBCtx, cs);
break;
case CONTENT_SETATTRIB:
content_set_attrib(WRBCtx, cs);
content_attrib(WRBCtx, cs);
break;
case CONTENT_DELETE:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
WRB_printf(WRBCtx, “<HTML>\n”);
default:
WRB_printf(WRBCtx, “Content-type: text/html\n\n”);
content_frameset(WRBCtx, cs);
break;
}
return (WRB_DONE);
}
WRB_CNTcloseRepository(WRBCtx, cs->hRepository);
return (WRB_DONE);
}
if (!WRBCtx || !cs)
return FALSE;
WRB_destroyPBlock(WRBCtx, content);
return TRUE;
exit_delete:
if (content)
WRB_destroyPBlock(WRBCtx, content);
return FALSE;
}
if (icx)
{
if (WRB_getParsedContent(WRBCtx, &content) != WRB_SUCCESS)
{
WRB_printf(WRBCtx, “Error in parsing querystring\n”);
return FALSE;
}
if (!file)
{
WRB_printf(WRBCtx, “Filename not specified\n”);
return FALSE;
}
WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
cs->hDoc = NULL;
return TRUE;
}
extn = content_extension(file);
mimetypes = WRB_getListenerInfo(WRBCtx, WRBL_MIMETYPES);
if (!(mimetype = WRB_findPBElemVal(WRBCtx, mimetypes, extn, -1)))
mimetype = (text *)”text/plain”;
WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
WRB_destroyPBlock(WRBCtx, content);
cs->hDoc = NULL;
return TRUE;
}
attributes = WRB_createPBlock(WRBCtx);
if (WRB_CNTgetAttributes(WRBCtx, cs->hDoc, attributes) < 0)
WRB_printf(WRBCtx, “</PRE>\n”);
WRB_printf(WRBCtx, “<BR><BR><P><h3> Set Document Attributes for
%s</h3>\n”, file);
WRB_printf(WRBCtx,
“<FORM METHOD=GET action=%s/tcont_set_attrib> \n\
<input type=hidden name=file value=%s> \n\
Name: <input type=text name=name1 size=20> <br>\n\
Value: <input type=text name=value1 size=30> <p> \n\
Name: <input type=text name=name2 size=20> <br>\n\
Value: <input type=text name=value2 size=30> <p> \n\
Name: <input type=text name=name3 size=20> <br>\n\
Value: <input type=text name=value3 size=30> <p>\n\
<INPUT TYPE=SUBMIT VALUE=\”Set Attrib\”> \n\
<INPUT TYPE=RESET VALUE=Reset> \n\
</FORM>\n”, cs->szVirtualPath, file);
WRB_printf(WRBCtx, “</HTML>\n”);
WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
cs->hDoc = NULL;
WRB_destroyPBlock(WRBCtx, content);
WRB_destroyPBlock(WRBCtx, attributes);
return TRUE;
exit_attrib:
WRB_printf(WRBCtx, “Error in listing attributes\n”);
WRB_printf(WRBCtx, “</HTML>\n”);
return FALSE;
}
if (!(attributes = WRB_createPBlock(WRBCtx)))
goto exit_set_attrib;
rval = TRUE;
exit_set_attrib:
if (cs->hDoc) WRB_CNTcloseDocument(WRBCtx, cs->hDoc);
return rval;
}
if (!WRBCtx || !cs)
return FALSE;
exit_list:
WRB_printf(WRBCtx, “<FORM METHOD=GET
ACTION=\"%s/tcont_upload_page\" \
target=\”main\”>\n\
<INPUT TYPE=SUBMIT VALUE=Upload>\n\
</FORM>”, cs->szVirtualPath);
return TRUE;
}
WRB_printf(WRBCtx,
“<FRAMESET COLS=\”35%,65%\” BORDER=\”3\”>\n\
<FRAME\n\
NAME=\”leftnav\” \n\
SRC=\” %s/tcont_list\”\n\
MARGINHEIGHT=5\n\
MARGINWIDTH=10\n\
SCROLLING = \”auto\”>\n\
<FRAME\n\
NAME=\”main\”\n\
SRC=\” %s/tcont_main\”\n\
MARGINHEIGHT=5\n\
MARGINWIDTH=10\n\
return TRUE;
}
return NULL;
}
6 Transaction Service
Example
This sample cartridge illustrates how to use the WRB Transaction Service with the OCI
database access API to perform database transactions.
#ifndef ORATYPES_ORACLE
# include <oratypes.h>
#endif
#ifndef WRB_ORACLE
# include <wrb.h>
#endif
#include <tx.h>
#include <ocidfn.h>
#include <ocikpr.h>
#include <stdio.h>
WRBReturnCode test_init();
WRBReturnCode test_exec();
WRBReturnCode test_shut();
testentry()
WRBReturnCode testentry (WRBCalls)
WRBCallbacks *WRBCalls;
{
WRBCalls->init_WRBCallback = test_init;
WRBCalls->exec_WRBCallback = test_exec;
WRBCalls->shut_WRBCallback = test_shut;
return (WRB_DONE);
}
test_init()
WRBReturnCode test_init( WRBCtx, clientcxp )
dvoid *WRBCtx;
dvoid **clientcxp;
{
int *count;
int retval;
AppCtx *ctx;
if (tx_reg(“SCOTT”) == TX_OK)
{
fprintf (stderr, “DAD_SCOTT open successful\n”);
retval = tx_set_transaction_timeout( 5 );
printf(“\n retval %d”, retval );
switch ( retval )
{
case TX_OUTSIDE:
fprintf( stderr, “ Calling cartridge not in txn context. \n” );
free(ctx);
return ( WRB_ERROR );
case TX_ERROR:
fprintf( stderr, “ Error in setting the timeout. \n” );
free(ctx);
return ( WRB_ERROR );
case TX_FAIL:
fprintf( stderr, “ Fatal error while setting timeout. \n” );
free(ctx);
return ( WRB_ABORT );
default:
printf (“Timeout for txn set. \n”);
break;
}
if (tx_open() != TX_OK)
{
fprintf (stderr, “Error in TX_openRM\n”);
fprintf (stderr, “\nProgram abort!!!\n”);
free(ctx);
return (WRB_ABORT);
}
ctx->count = 0;
*clientcxp = (void *)ctx;
}
else
{
fprintf (stderr, “Error in open DAD_SCOTT\n”);
free(ctx);
return (WRB_ABORT);
}
return (WRB_DONE);
}
test_exec()
WRBReturnCode test_exec( WRBCtx, clientcxp )
dvoid *WRBCtx;
dvoid *clientcxp;
{
int bufl;
char *uri;
AppCtx *ctx = (AppCtx *)clientcxp;
char buf[1024];
TXINFO *info;
text db_name[6] = “SCOTT”;
WAPIReturnCode rc;
ctx->count++;
}
else if (strstr(uri, “committxn”))
{
printf(“\ninfo return :%d, state : %d\n”, tx_info(info),
(int)info->transaction_state );
}
else if (strstr(uri, “rollbacktxn”))
{
printf(“\ninfo return :%d, state : %d\n”, tx_info(info),
(int)info->transaction_state );
if ((!tx_info(info)) && (info->transaction_state == TX_ACTIVE ))
{
if (tx_rollback() == TX_OK)
WRB_printf(WRBCtx, (text *)”Transaction rollbacked\n”);
else
{
WRB_printf(WRBCtx, (text *)”Error in Transaction rollback\n”);
free(info);
return WRB_ABORT;
}
}
else
WRB_printf(WRBCtx, (text *)”Not in transactional context\n”);
}
else if (strstr (uri, “exit”))
{
tx_close();
free(info);
return WRB_ABORT;
}
else if (strstr (uri, “select”) || strstr(uri, “update”))
Lda_Def lda;
Cda_Def cda;
sb4 len = -1;
text emp_name[64];
sword empno, salary;
text *sql;
do
{
if ((!tx_info(info)) && (info->transaction_state == TX_INACTIVE ))
{
WRB_printf(WRBCtx, (text *)”Not in transactional context\n”);
break;
}
if (strstr(uri, “select”))
sql = select;
else
sql = update;
if (strstr(uri, “select”))
{
sb2 ind_ename, ind_empno, ind_sal;
ub2 retc_ename, retc_empno, retc_sal;
if (oexec (&cda))
{
fprintf(stderr, “error in oexec\n”);
oerhms(&lda, cda.rc, buf, sizeof(buf));
break;
}
if (strstr(uri, “select”))
{
if (ofetch(&cda))
{
fprintf(stderr, “error in ofetch\n”);
oerhms(&lda, cda.rc, buf, sizeof(buf));
break;
}
WRB_printf(WRBCtx, (text *)”<br>Employee name: %s, ID: %d, Salary %d<br>”,
emp_name, empno, salary);
}
else
WRB_printf(WRBCtx, (text *)”Employee salary updated<br>”);
} while (FALSE);
}
else if ((!tx_info(info)) && (info->transaction_state == TX_ACTIVE ))
WRB_printf(WRBCtx, (text *)”TXN Hello World in Transaction\n”);
else
WRB_printf(WRBCtx, (text *)”TXN Hello World not in Transaction yet\n”);
free(info);
return (WRB_DONE);
}
test_shut()
WRBReturnCode test_shut( WRBCtx, clientcxp )
dvoid *WRBCtx;
dvoid *clientcxp;
{
free(clientcxp);
See Overview of the Web Request Broker (WRB) and Designing Your Application for
details on architecture of the WRB and how to structure your applications.
Contents
• WRB_addPBElem() - Adds an element to a parameter block
• WRB_annotateURL() - Writes a URL with appended query string
• WRB_apiVersion() - Returns the current version of the WRB.
• WRB_copyPBlock() - Copies a parameter block
• WRB_createPBlock() - Creates a parameter block
• WRB_delPBElem() - Deletes an element from a parameter block
• WRB_destroyPBlock() - Destroys a parameter block
• WRB_findPBElem() - Finds an element by name in a parameter block
• WRB_findPBElemVal() - Finds the value of a parameter block element
• WRB_firstPBElem() - Finds the first element in a parameter block
• WRB_getAppConfigSection() - Gets cartridge configuration data
• WRB_getAppConfigVal() - Gets the value of a configuration parameter
• WRB_getCartridgeName() - Gets the name of the calling cartridge
• WRB_getClientCert() - Gets an SSL certificate from the client
• WRB_getCookies() - Gets cookie data from the current request header
• WRB_getEnvironment() - Gets the cartridge environment variables
• WRB_getListenerInfo() - Gets information about a Web Listener
• WRB_getMultAppConfigSection() - Gets data for multiple cartridges
• WRB_getMultipartData() - Gets data from a multipart form.
• WRB_getParsedContent() - Gets request content as name-value pairs
• WRB_getPreviousError() - Gets the most recent error
• WRB_getRequestInfo() - Gets information about the current request
• WRB_nextPBElem() - Gets the next element in a parameter block
• WRB_numPBElem() - Gets the number of elements in a parameter block
• WRB_printf() - Writes a formatted text string
• WRB_read() - Reads POST data from the requestor
• WRB_recvHeaders() - Gets the request headers
• WRB_sendHeader() - Sends the response header to the requestor
• WRB_setCookies() - Sets cookie data in the response header
• WRB_setAuthBasic() - Creates a new basic authentication realm
• WRB_setAuthDigest() - Creates a new digest authentication realm
• WRB_setAuthServer() - Uses the authentication server for authentication
• WRB_timestamp() - Writes an entry in the log file when this function is
executed
• WRB_walkPBlock() - Finds an element by position in a parameter block
• WRB_write() - Writes response data to the requestor
Syntax
WAPIReturnCode WRB_addPBElem(
dvoid *WRBCtx,
WRBpBlock hPBlock,
text *szParamName,
sb4 nParamName,
text *szParamValue,
sb4 nParamValue,
ub2 nParamType);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_createPBlock()
You can use this function to set the value of the HREF attribute of the HTML A (anchor)
tag. The function translates special characters such as & and = in the name-value pairs
to corresponding %x values (where x is an integer in hexadecimal format) before
appending them to the URL.
Syntax
sb4 WRB_annotateURL(
dvoid *WRBCtx,
text *url,
WRBpBlock hArguments);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ url The text of the base URL without the query string,
including “http://”, the hostname, port (if necessary),
and the URI.
Return Values
The number of bytes written to the requestor, or –1 when an error occurs.
Syntax
ub2 WRB_apiVersion(dvoid *WRBCtx);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
A version number.
Example
You should call this function in your cartridge’s Init callback to determine if your
cartridge is compatible with the user’s WRB:
WRBAPI_CURRENT_VERSION defines the version of the WRB that was used to build
the cartridge. The code above aborts the cartridge if the current version is earlier than
the version that is used by the cartridge.
Syntax
WRBpBlock WRB_copyPBlock(
dvoid *WRBCtx,
WRBpBlock hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WRBpBlock that identifies a copy of the specified parameter block.
WRB_copyPBlock() returns NULL on failure.
See Also
WRB_createPBlock() and WRB_destroyPBlock()
Syntax
WRBpBlock WRB_createPBlock (dvoid *WRBCtx);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A variable of type WRBpBlock that identifies the newly created parameter block.
WRB_createPBlock() returns NULL on failure.
See Also
WRB_destroyPBlock()
Syntax
WAPIReturnCode WRB_delPBElem (
dvoid *WRBCtx,
WRBpBlock hPBlock,
text *szName,
sb4 nNamel);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ nName1 The length in bytes of the element name. If you set this
parameter to –1, the function uses the strlen() library
function to determine the length of the element name.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_addPBElem()
Syntax
WAPIReturnCode WRB_destroyPBlock(
dvoid *WRBCtx,
WRBpBlock hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
WRB_destroyPBlock() returns a value of type WAPIReturnCode.
Usage
You must call WRB_destroyPBlock() on a parameter block when you are finished
using it.
Examples
See the MyWRBApp function placeOrder().
See Also
WRB_createPBlock()
Syntax
WRBpBlockElem * WRB_findPBElem(
dvoid *WRBCtx,
WRBpBlock hPBlock,
text *szName,
sb4 nNamel);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ nNamel The length in bytes of the element name. If you set this
parameter to –1, the function uses the strlen() library
function to determine the length of the element name.
Return Values
A pointer to the parameter block element identified by szName. WRB_findPBElem()
returns NULL on failure.
See Also
WRB_createPBlock(), WRB_findPBElemVal()
Syntax
text * WRB_findPBElemVal(
dvoid *WRBCtx,
WRBpBlock hPBlock,
text *szName,
sb4 nNamel);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ nNamel The length in bytes of the element name. If you set this
parameter to –1, the function uses the strlen() library
function to determine the length of the element name.
Return Values
A pointer to text string containing the value of the parameter block element identified
by szName. WRB_findPBElemVal() returns NULL on failure.
Examples
See the MyWRBApp function newUser()
See Also
WRB_createPBlock()
Note: The returned value is valid only until the retrieved element is deleted.
Syntax
WRBpBlockElem *
WRB_firstPBElem(dvoid *WRBCtx,
WRBpBlock hPBlock,
dvoid **pos);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the first element in a parameter block element. WRB_firstPBElem()
returns NULL on failure.
Examples
WRBpBlock hPBlock;
WRBpBlockElem *elem;
dvoid *pos;
See Also
WRB_nextPBElem() and WRB_createPBlock()
You must call WRB_destroyPBlock() on the parameter block when you are finished
with it.
Syntax
WAPIReturnCode
WRB_getAppConfigSection(dvoid *WRBCtx
text *szSectionName
WRBpBlock *hSection);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
You can use WRB_getAppConfigSection() in conjunction with
WRB_firstPBElem() and WRB_nextPBElem() to retrieve all name-value pairs
from a named section of the WRB configuration. This example retrieves and iterates
through the name-value pairs defined for the calling cartridge:
text *cartname;
WRBpBlock hPBlock;
WAPIReturnCode ret;
WRBpBlockElem *elem;
dvoid *pos;
cartname = WRB_getCartridgeName(WRBCtx);
ret = WRB_getAppConfigSection(WRBCtx, cartname, &hPBlock);
if (ret != WRB_SUCCESS) {
return (WRB_ERROR);
}
WRB_destroyPBlock(WRBCtx, hPBlock);
See Also
WRB_getAppConfigVal() and WRB_getMultAppConfigSection()
Syntax
text *
WRB_getAppConfigVal(dvoid *WRBCtx
text *szSectionName
text *szName);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
WRB_getAppConfigVal() returns a pointer to a text string containing the value of
the specified parameter defined in the specified section of the WRB configuration data.
Examples
See the MyWRBApp function MyWRBApp_Reload().
See Also
WRB_getAppConfigSection() and WRB_getCartridgeName()
Syntax
text *
WRB_getCartridgeName(dvoid *WRBCtx);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to a text string containing the name by which the calling cartridge is
identified in the WRB configuration data.
See Also
WRB_getAppConfigSection(), WRB_getMultAppConfigSection(), and
WRB_getAppConfigVal()
Syntax
WAPIReturnCode WRB_getClientCert(
dvoid *WRBCtx,
ub1 **cert,
ub4 *certlen);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
A value of type WAPIReturnCode.
Example
WAPIReturnCode r;
FILE *fp;
ub1 *cert;
ub4 certlen;
When you are finished with the parameter block, you must call
WRB_destroyPBlock() to free it.
Syntax
WAPIReturnCode
WRB_getCookies(dvoid *WRBCtx,
WRBpBlock *hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
WRBpBlock hPBlock;
WAPIReturnCode ret;
WRBpBlockElem *elem;
dvoid *pos;
WRB_destroyPBlock(WRBCtx, hPBlock);
See Also
WRB_setCookies() and WRB_destroyPBlock()
When you are finished with the parameter block containing the data, you must call
WRB_destroyPBlock() to free the memory used by the parameter block.
Note that this function cannot be called during the init callback because it requires a
client context. When the init callback executes, there is no client context.
Syntax
WAPIReturnCode WRB_getEnvironment(
dvoid *WRBCtx,
WRBpBlock *hEnvironment);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
This example uses WRB_getEnvironment() with WRB_findPBElemVal() to
retrieve the value of a specific environment variable:
WRBpBlock hPBlock;
WAPIReturnCode ret;
text *owhome;
WRB_destroyPBlock(WRBCtx, hPBlock);
See Also
WRB_findPBElemVal() and WRB_destroyPBlock()
Syntax
WRBpBlock
WRB_getListenerInfo(dvoid *WRBCtx,
ub2 nInfoType);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A parameter block containing the requested information about the Web Listener that
forwarded the current request. WRB_getListenerInfo() returns NULL on failure.
You must call WRB_destroyPBlock() on the parameter block when you are finished
with it.
Syntax
WAPIReturnCode WRB_getMultAppConfigSection(
dvoid *WRBCtx,
text *szSectionName,
WRBpBlock *pSectionList);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
You can use WRB_getMultAppConfigSection() with WRB_firstPBElem() and
WRB_nextPBElem() to retrieve all name-value pairs from the specified sections of the
WRB configuration. This example retrieves and iterates through the name-value pairs
defined in all sections with names starting with “jane”:
WRBpBlock hPBlock;
WAPIReturnCode ret;
WRBpBlockElem *sect, *elem;
dvoid *sectpos, *pos;
WRB_destroyPBlock(WRBCtx, hPBlock);
See Also
WRB_getAppConfigVal() and WRB_getAppConfigSection()
For example, if you are uploading files, each part in your request would contain:
• a name-value pair where the name is the name of the header (for instance, “file”),
the value is the name of the file you are uploading. This information is returned
in the multiPart parameter.
• the data, which would be the contents of the file. This information is returned in
the mpData parameter.
Each call to this function returns data for one part in the form. To get all parts, you call
this function repeatedly until it does not return NULL.
Syntax
WAPIReturnCode
WRB_getMultipartData(
dvoid *WRBCtx,
WRBpBlockElem *multiPart,
ub1 *mpData,
ub4 mpDataLen);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
A value of type WAPIReturnCode.
Example
This example retrieves the value of the file and file_data headers from a
multipart form.
Syntax
text *
WRB_getORACLE_HOME(dvoid *WRBCtx);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The value of the ORACLE_HOME environment variable, or NULL if
ORACLE_HOME is not set.
See Also
WRB_getEnvironment()
This function parses this data and passes it back in a parameter block. Each element in
the parameter block contains the name and value of a POST data or query string entry.
When you are finished with the parameter block containing the data, you must call
WRB_destroyPBlock() to free the memory used by the parameter block.
Syntax
WAPIReturnCode
WRB_getParsedContent(dvoid *WRBCtx, WRBpBlock *hQueryString);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
You can use WRB_getParsedContent() with WRB_firstPBElem() and
WRB_nextPBElem() to retrieve the current request’s query string or POST data:
WRBpBlock hPBlock;
WAPIReturnCode ret;
WRBpBlockElem *elem;
dvoid *pos;
WRB_destroyPBlock(WRBCtx, hPBlock);
Syntax
boolean WRB_getPreviousError(
dvoid *WRBCtx,
sword *nErrorNum,
text **sErrorMesg,
ub4 *nErrorMesgl);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
TRUE if an error has been logged, FALSE otherwise.
Syntax
text *
WRB_getRequestInfo(dvoid *WRBCtx,
ub2 nInfoType);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Value Description
WRBR_URI Request URI.
WRBR_URL Request URL.
WRBR_LISTENERTYPE The type of listener, such as Oracle Web
Application Server.
WRBR_VIRTUALPATH Request Virtual path (a substring of the
request URI).
WRBR_PHYSICALPATH Physical path, if any, to which the virtual
path is mapped.
WRBR_QUERYSTRING Query String of the request.
WRBR_LANGUAGE Comma-separated list of languages the
requestor can accept.
WRBR_ENCODING Comma-separated list of encodings the
requestor can accept.
WRBR_REQMIMETYPE MIME type of the request.
WRBR_USER The username provided by the requestor in
response to an authentication challenge.
WRBR_PASSWORD The password provided by the requestor in
response to an authentication challenge.
WRBR_IP The requestor’s IP address in dotted quad
notation.
Note: The returned value is valid only until the retrieved element is deleted.
Syntax
WRBpBlockElem *
WRB_nextPBElem(dvoid *WRBCtx,
WRBpBlock hPBlock,
dvoid *pos);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the next available element in a parameter block element.
WRB_nextPBElem() returns NULL on failure.
Examples
WRBpBlock hPBlock;
WRBpBlockElem *elem;
dvoid *pos;
See Also
WRB_firstPBElem()
Syntax
sb4
WRB_numPBElem (dvoid *WRBCtx,
WRBpBlock hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of elements in a specified parameter block.
Examples
See the WRB_walkPBlock() example.
See Also
WRB_walkPBlock()
Use this function in the same way as the standard C printf function to format and
write text strings to the requestor. Like printf, it accepts a variable number of
arguments.
Syntax
sb4 WRB_printf(
dvoid *WRBCtx,
text *formatStr,
...);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes written, or –1 if an error occurs.
See Also
WRB_read() and WRB_write()
You can call this function from your Exec function to get the POST data associated with
the current request. This function is especially useful for buffering raw POST data.
If the POST data is in the form of name-value pairs, however, it is usually more
convenient to call WRB_getParsedContent() instead.
Syntax
sb4
WRB_read(dvoid *WRBCtx,
text *sBuffer,
sb4 nBufferSize);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes read, or –1 if an error occurs.
See Also
WRB_getParsedContent(), WRB_write()
When you are finished with the parameter block, you must call
WRB_destroyPBlock() to free it.
Syntax
WAPIReturnCode
WRB_recvHeaders(dvoid *WRBCtx,
WRBpBlock *hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
You can use WRB_recvHeaders() in conjunction with WRB_firstPBElem() and
WRB_nextPBElem() to retrieve the request headers:
WRBpBlock hPBlock;
WAPIReturnCode ret;
WRBpBlockElem *elem;
dvoid *pos;
WRB_destroyPBlock(WRBCtx, hPBlock);
See Also
WRB_setCookies() and WRB_destroyPBlock()
If you want to redirect a request to another URL, you should not use the WRB 2.1
function WRBReturnHTTPRedirect(). Instead, you should add a parameter block
element with the name “Location” and a value containing the URL to which you
want to redirect the request. You can then call WRB_sendHeader() on this parameter
block to redirect the request.
Syntax
WAPIReturnCode
WRB_sendHeader(dvoid *WRBCtx,
WRBpBlock hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode. If you call WRB_sendHeader() after calling
WRB_write(), WRB_sendHeader() fails and returns WRB_TOOLATE.
See Also
WRB_createPBlock(), WRB_addPBElem(), and WRB_write()
You can call this function in your Authorize function to create a basic authentication
realm that your cartridge can use to authenticate requestors. If your cartridge uses this
function to create a realm, your Authorize function is responsible for authentication for
your cartridge.
The WRB caches the realm specified by szRealm whenever this function is called. If
your Authorize function returns indicating that the client is not authorized, the WRB
used the cached realm name in formulating an error message to be returned to the
client.
Syntax
WAPIReturnCode
WRB_setAuthBasic(dvoid *WRBCtx,
text *szRealm);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
See the MyWRBApp function MyWRBApp_Authorize().
See Also
WRB_setAuthDigest() and WRB_setAuthServer()
You can call this function in your Authorize function to create a digest authentication
realm that your cartridge can use to authenticate requestors. If your cartridge uses this
function to create a realm, your Authorize function is responsible for authentication for
your cartridge.
The WRB caches the values specified by the sz* parameters whenever this function is
called. If your Authorize function returns indicating that the client is not authorized,
the WRB used the cached realm name in formulating an error message to be returned
to the client.
Syntax
WAPIReturnCode
WRB_setAuthDigest(dvoid *WRBCtx,
text *szRealm,
text *szOpaque,
text *szNonce,
text *szStale);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_setAuthBasic() and WRB_setAuthServer()
You can call this function in your Init or Authorize function to specify a combination
of existing authentication and/or restriction schemes for the authentication server to
use in authenticating requestors issuing requests to your cartridge. You must encode
the schemes in the szProtectString parameter as follows:
where op is one of ‘&’ (the “and” operator) or ‘|’ (the “or” operator). The square
brackets are not part of the syntax, but indicate that additional scheme(realm) pairs are
optional. These expressions may not be grouped; the operators are evaluated strictly
from left to right.
For authentication schemes, realm must be an authentication realm defined in the WRB
configuration data.
For restriction schemes, realm must be the name of a group of IP addresses or DNS
domain names defined in the WRB configuration.
Note that if you call this function in the cartridge’s Init callback, the cartridge’s
Authorize callback is not called.
Syntax
WAPIReturnCode
WRB_setAuthServer(dvoid *WRBCtx,
text *szProtectStr);
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
In this example, the call to WRB_setAuthServer() requires that requestors issuing
requests to the calling cartridge authenticate themselves using the Basic authentication
realm “Admin Server”, defined in the WRB configuration. It also requires that
requestors IP addresses be in the “HQ Hosts” group of IP addresses, defined in the
WRB configuration:
WAPIReturnCode ret;
ret = WRB_setAuthServer(WRBCtx,
(text *)"Basic(Admin Server) & IP(HQ Hosts)");
if (ret != WRB_SUCCESS) {
return (WRB_ERROR);
}
See Also
WRB_setAuthBasic() and WRB_setAuthDigest()
Syntax
WAPIReturnCode WRB_setCookies(dvoid *WRBCtx,
text *name,
text *value,
text *domain,
text *path,
text *expire,
boolean secure);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ path The URI path for which you want the requestor to send
the cookie. This is often a URI that refers to your
cartridge.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_getCookies()
Before you can use this function, you need enable the time-stamping mechanism by
adding this line in the [SYSTEM] section of the wrb.app file:
[SYSTEM]
enable_timing_stats = logger
Typically, you would call this function at the beginning and end of an operation to
measure how long the operation takes.
Syntax
void WRB_timestamp(
dvoid *WRBCtx,
ub4 locID);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
Nothing.
You can use this function with WRB_numPBElem() to iterate through the elements of
a parameter block.
Note: The returned value is valid only until the retrieved element is deleted.
The WRB API in wrb.h needs to clarify that WRB_walkPBlock does not necessarily
iterate through the elements in the header in order.
Syntax
WRBpBlockElem *
WRB_walkPBlock (dvoid *WRBCtx,
WRBpBlock hPBlock,
sb4 nPosition);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the element at a specified position in a parameter block, or NULL on
failure.
Examples
WRBpBlockElem *elem;
sb4 numelems;
See Also
WRB_findPBElem()
Syntax
sb4
WRB_write(dvoid *WRBCtx,
text *sBuffer,
sb4 nBufferSize);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes written, or –1 when an error occurs.
See Also
WRB_printf(), WRB_read()
text *szParamValue;
sb4 nParamValue;
ub2 nParamType;
dvoid *pNVdata;
} WRBpBlockElem;
The nParamName and nParamValue members represent the length in bytes of the
szParamName and szParamValue members.
Value Meaning
WRBPT_DONTCARE Leaves the element type unspecified.
WRBPT_NUMBER The element is a number.
WRBPT_STRING The element is a character string.
WRBPT_DATE The element is a calendar date in SQL date type
format.
WRBPT_RAW The element value is raw binary data.
The pNVdata member is used for various purposes by some WRB API functions.
Value Description
WRB_NOTLOADED The function is part of a WRB service that is not
loaded.
WRB_LOWMEM The function could not allocate memory.
WRB_FAIL The function had an internal error.
WRB_SUCCESS The function completed successfully.
WRB_TOOLATE You tried to send header data after beginning to
write content data.
WRB_AUTHNEEDED You must supply the required authentication data
and WRBMethod Enumerated Type again.
WRB_MOREDATA WRBMethod Enumerated Type returned with a
partial response: you must call WRBMethod
Enumerated Type repeatedly until you have
received the entire response.
Table 1:
Note: Some WRB API functions return values of type WAPIReturnCode instead.
struct WRBCallbacks
{
WRBReturnCode (*init_WRBCallback)();
WRBReturnCode (*exec_WRBCallback)();
WRBReturnCode (*shut_WRBCallback)();
WRBReturnCode (*reload_WRBCallback)();
char *(*version_WRBCallback)();
void (*version_free_WRBCallback)();
WRBReturnCode (*authorize_WRBCallback)();
};
typedef struct WRBCallbacks WRBCallbacks;
Note: The APIs in this section are available only in the Advanced version of the Web
Application Server. They are not available in the Standard version.
These APIs allow access to web content repositories from WRB cartridges using a
simple set of interfaces reminiscent of standard UNIX file system access library
functions.
For a description of WRB cartridges and a general overview of the WRB architecture,
see the Overview of the Web Request Broker (WRB).
To learn about the general steps involved in developing WRB cartridges, see Designing
Your Application.
You must open a repository before you can access the documents it contains.
Syntax
dvoid *
WRB_CNTopenRepository (dvoid *WRBCtx,
text *user,
text *passwd,
text *connectstr);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A handle to the specified repository, or NULL on failure. You can call
WRB_getPreviousError() to get more information about the error if there was a failure.
Examples
See the MyWRBApp function MyWRBApp_Init().
See Also
WRB_CNTcloseRepository() and WRB_CNTopenDocument().
Syntax
WAPIReturnCode
WRB_CNTcloseRepository (dvoid *WRBCtx,
dvoid * hRepository);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
See the MyWRBApp function MyWRBApp_Shutdown().
See Also
WRB_CNTopenRepository().
You must call this function on a document before you can call
WRB_CNTreadDocument() or WRB_CNTwriteDocument() to access the document.
Syntax
dvoid *
WRB_CNTopenDocument (dvoid *WRBCtx,
dvoid *hRepository,
text *szDocName,
ub2 mode);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A handle to the specified document, or NULL on failure.
Examples
See the MyWRBApp function getCatalog().
See Also
WRB_CNTcloseDocument(), WRB_CNTopenRepository(),
WRB_CNTreadDocument(), WRB_CNTwriteDocument().
You should call this function to close a document when you have finished accessing it.
Any changes you have made to your private copy of the document by calling
WRB_CNTwriteDocument() are applied to the original document before it is closed.
Syntax
WAPIReturnCode
WRB_CNTcloseDocument (dvoid *WRBCtx,
dvoid *hDocument);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Examples
See the MyWRBApp function getCatalog().
See Also
WRB_CNTopenDocument().
You can use this function to delete a document permanently from a content repository.
You must call WRB_CNTopenRepository() first to get a handle to the repository that
contains the document you want to destroy.
Syntax
WAPIReturnCode
WRB_CNTdestroyDocument (dvoid *WRBCtx,
dvoid * hRepository,
text *szDocName);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_CNTopenRepository().
Syntax
WAPIReturnCode
WRB_CNTgetAttributes(dvoid *WRBCtx,
dvoid *hDocument,
WRBpBlock hAttributes);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Usage
You can use this function to get the following information about a document in a
content repository. The attribute types referred to below are defined in The Parameter
Block Element Structure.
Examples
WRBpBlockElem *attrib_elem;
sb4 num_attributes;
WAPIReturnCode ret;
int i;
if (ret == WRB_SUCCESS) {
num_attributes = WRB_numPBElem(WRBCtx, hAttributes);
for (i = 0; i < num_attributes; i++) {
attrib_elem = WRB_walkPBlock(WRBCtx, hAttributes, i);
/* do something with attribute */
}
}
Syntax
WAPIReturnCode
WRB_CNTsetAttributes(dvoid *WRBCtx,
dvoid *hDocument,
WRBpBlock hAttributes);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_CNTgetAttributes() and WRB_CNTopenDocument().
Syntax
sb4 WRB_CNTreadDocument(
dvoid *WRBCtx,
dvoid *hDocument,
ub1 *buffer,
sb4 buffersz);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes successfully read from the specified document.
Examples
See the MyWRBApp function myfgets().
See Also
WRB_CNTwriteDocument() and WRB_CNTopenDocument().
When you call this function to modify a document, you modify your own private copy
of the document. To apply these changes to the original document, you must call
WRB_CNTflushDocument() or close the document by calling
WRB_CNTcloseDocument().
Syntax
sb4
WRB_CNTwriteDocument (dvoid *WRBCtx,
dvoid * hDocument,
ub1 *buffer,
sb4 buffersz);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes successfully written to the specified document.
Examples
See the MyWRBApp function storeInfo().
See Also
WRB_CNTreadDocument() and WRB_CNTopenDocument().
When you call WRB_CNTwriteDocument(), you modify your own private copy of a
document in a content repository. To apply those changes to the original document,
you must call WRB_CNTflushDocument(). If you are finished with the document,
you can call WRB_CNTcloseDocument(), which flushes the document before closing
it.
Syntax
WAPIReturnCode
WRB_CNTflushDocument (dvoid *WRBCtx,
dvoid * hDocument);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_CNTwriteDocument() and WRB_CNTopenDocument().
Syntax
sb4
WRB_CNTlistDocuments (
dvoid *WRBCtx,
dvoid *hRepository
WRBpBlock *docList);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of documents.
9 WRB Inter-Cartridge
Exchange Service API
Reference
The Inter-cartridge Exchange Service (ICX) can issue HTTP requests between WRB
cartridges. For a description of WRB cartridges and a general overview of the WRB
architecture, see “Overview of the Web Request Broker (WRB)”.
To learn about the general steps involved in developing WRB cartridges, see
“Designing Your Application”.
Contents
• Benefits of Using ICX
• Example Code
• WRB Inter-Cartridge Exchange Service API Functions
• Data Types
/* create a request */
if (!(reqp = WRB_ICXcreateRequest(WRBCtx, (text
*)”http://www.oracle.com”)))
{
return WRB_ERROR;
}
/* execute the request and send the result directly to the browser*/
rval = WRB_ICXmakeRequest(WRBCtx, reqp, (void **)&response,
&responseLength, chunkSize,TRUE);
if (rval == WRB_FAIL)
{
return WRB_ERROR;
}
else
{
return WRB_DONE;
}
}
Data Types
• WRBInfoType Enumerated Type
• WRBMethod Enumerated Type
Syntax
dvoid* WRB_ICXcreateRequest(
dvoid *WRBCtx,
text *url);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A handle to the newly created request object, or NULL on failure.
See Also
WRB_ICXmakeRequest() and WRB_ICXdestroyRequest().
Syntax
WAPIReturnCode
WRB_ICXdestroyRequest(dvoid *WRBCtx,
dvoid *hRequest);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXcreateRequest() and WRB_ICXmakeRequest().
Syntax
WRBAPIReturnCode
WRB_ICXfetchMoreData(dvoid *WRBCtx,
dvoid *hRequest,
dvoid **response,
ub4 *responseLength,
ub4 chunkSize);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
Usage
If a call to WRB_ICXmakeRequest() returns WRB_MOREDATA, you can call
WRB_ICXfetchMoreData() repeatedly to retrieve chunkSize more bytes of the
request response until all response data has been received.
Examples
WAPIReturnCode ret;
dvoid *hRequest;
ub4 bufsize = 1024;
void buf[bufsize];
ub4 respLength;
/* destroy request */
See Also
WRB_ICXmakeRequest(), WRB_ICXcreateRequest(), WRB_ICXsetMethod(),
WRB_ICXsetAuthInfo(), WRB_ICXsetHeader() and WRB_ICXsetContent().
This is especially useful for retrieving response data that is stored only in the response
headers.
Syntax
text *
WRB_ICXgetHeaderVal(dvoid *WRBCtx,
dvoid *hRequest,
text *name);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The value of the specified header, or NULL on failure.
See Also
WRB_ICXgetInfo().
Syntax
text *
WRB_ICXgetInfo(dvoid *WRBCtx,
dvoid *hRequest,
WRBInfoType infoType);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pioneer to the requested information as a character string, or NULL on failure.
This is especially useful for retrieving response data that is stored only in the response
headers.
Syntax
WAPIReturnCode
WRB_ICXgetParsedHeader(dvoid *WRBCtx,
dvoid *hRequest,
WRBpBlock *hPblock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXgetHeaderVal().
Syntax
WAPIReturnCode
WRB_ICXmakeRequest(dvoid *WRBCtx,
dvoid *hRequest,
dvoid **response,
ub4 *responseLength,
ub4 chunkSize,
ub1 sendToBrowser);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXcreateRequest(), WRB_ICXsetMethod(), WRB_ICXsetAuthInfo(),
WRB_ICXsetHeader() and WRB_ICXsetContent().
If your cartridge issues requests to another cartridge that requires your cartridge to
authenticate itself, you can call this function to set the authentication header data for
each request to the other cartridge.
Syntax
WAPIReturnCode
WRB_ICXsetAuthInfo(dvoid *WRBCtx,
dvoid *hRequest,
text *username,
text *password);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
To set content data for a request, you must first call WRB_createPBlock() to allocate
a parameter block containing the content data. Then, you can pass the parameter block
to WRB_ICXsetContent(). You specify the request by passing the request handle
returned by WRB_ICXcreateRequest().
Syntax
WAPIReturnCode
WRB_ICXsetContent(dvoid *WRBCtx,
dvoid *hRequest,
WRBpBlock hPBlock);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXcreateRequest() and WRB_ICXsetHeader().
To set header data for a request, you must first call WRB_createPBlock() to allocate
a parameter block and containing the header data. Then, you can pass the parameter
block to WRB_ICXsetHeader(). You specify the request by passing the request
handle returned by WRB_ICXcreateRequest().
Syntax
WAPIReturnCode
WRB_ICXsetHeader(dvoid *WRBCtx,
dvoid *hRequest,
WRBpBlock hPBlock,
boolean useOldHdr);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXcreateRequest() and WRB_ICXsetContent().
Syntax
WAPIReturnCode
WRB_ICXsetMethod(dvoid *WRBCtx,
dvoid *hRequest,
WRBMethod method);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXcreateRequest().
Instead of calling this function, you can set the no_proxy environment variable to a
comma-separated list of domains to which requests should be sent directly.
Syntax
WAPIReturnCode
WRB_ICXsetNoProxy(dvoid *WRBCtx,
text *noProxy);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXsetProxy().
If your cartridge is running on a machine inside a firewall and needs to issue ICX
requests to machines outside the firewall, you can use WRB_ICXsetProxy() to
specify the address of a proxy server that can send requests outside the firewall.
Instead of calling this function, you can set the http_proxy environment variable to
the name of the proxy server to use.
Syntax
WAPIReturnCode
WRB_ICXsetProxy(dvoid *WRBCtx,
text *proxyAddress);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_ICXsetNoProxy().
Value Meaning
OPTIONS
GET
HEAD
POST
PUT
DELETE
TRACE
Note: The APIs in this section are available only in the Advanced version of the Web
Application Server. They are not available in the Standard version.
The Transaction Service interface replaces the old WRB_TXN interface. See “Migrating
to the New TX Interface” for information on how to migrate your cartridge to use the
new interface.
Note: For Transaction Service to work for your cartridge, you need to enable it for your
cartridge. You can do this from any of these forms in the Web Application Server
Manager:
For an example of using the WRB Transaction Service API, see “Transaction Service
Example”.
For a description of WRB cartridges and a general overview of the WRB architecture,
see “Overview of the Web Request Broker (WRB)”. To learn about the general steps
involved in developing WRB cartridges, see “Designing Your Application”.
Data Type
• TXINFO Structure - A struct that contains information about the current
transaction
You can use this function to send the current transaction ID to the requestor in the form
of a cookie. The client can then send this transaction ID with subsequent requests to
identify the transaction to which they apply.
Syntax
int tx_annotate_path (text *path);
Parameters
Return Values
• TX_OK
• TX_ERROR
Usage
For example, if you are writing a cartridge called “mycart”, and your Exec function
supports “begin”, “update”, “commit”, and “rollback” requests, your Exec function
can call tx_annotate_path() in the following ways:
tx_annotate_path((text *)"/mycart/commit");
tx_annotate_path((text *)"/mycart/rollback");
tx_annotate_path((text *)"/mycart/commit");
tx_annotate_path((text *)"/mycart/rollback");
commit (nothing)
rollback (nothing)
If these are the only requests you define, you can just make a single call while handling
“begin” and “update”:
If you want your cartridge to support clients that cannot or will not accept cookies, you
can use tx_annotate_url() instead of tx_annotate_url().
See Also
tx_annotate_url().
Syntax
int tx_annotate_url (text *url, text **annotatedUrl);
Parameters
Return Values
• TX_OK
• TX_ERROR
Usage
You can use tx_annotate_url() instead of tx_annotate_path() in cartridges
that must support clients that cannot or will not accept cookies. To do this, you must
generate a response to the request that contains explicit links to URLs for anticipated
future requests that should be handled as part of the current transaction.
You must therefore call tx_annotate_url() from the section of code that generates
the HTML response to the request.
Examples
text *annotatedUrl;
/* output headers... */
tx_annotate_url("/mycart/update", &annotatedUrl);
WRB_printf(WRBCtx,
(text *)"<FORM ACTION=\"%s\" METHOD=\"POST\">\n",
annotatedUrl);
See Also
tx_annotate_path().
You must call tx_open() to connect to one or more resource managers before calling
tx_begin().
See The Transaction Model in Designing Your Application for more information about
transaction semantics.
Syntax
int tx_begin (void);
Parameters
none
Return Values
• TX_OK
• TX_OUTSIDE - The calling cartridge is not transaction enabled.
• TX_PROTOCOL_ERROR - The calling cartridge is already in transactional
mode.
• TX_FAIL - Fatal Error. The calling cartridge must return WRB_ABORT.
See Also
tx_open(), tx_commit(), tx_rollback().
Syntax
int tx_close (void);
Parameters
none
Return Values
• TX_OK
• TX_OUTSIDE - The calling cartridge is not transaction enabled.
• TX_ERROR - Transient error in closing one or more resource managers.
• TX_FAIL - Fatal error. The calling cartridge must return WRB_ABORT.
See Also
tx_open().
Syntax
int tx_commit (void);
Parameters
none
Return Values
• TX_OK
• TX_OUTSIDE - The calling cartridge is not transaction enabled.
• TX_ROLLBACK - The commit failed, and a rollback is in progress.
• TX_MIXED - The commit was partially successful, and partial rollback is in
progress.
• TX_FAIL - Fatal error. The calling cartridge must return WRB_ABORT.
See Also
tx_begin(), tx_rollback().
You must allocate the TXINFO structure yourself and pass a pointer to it to the
function. See TXINFO Structure for more information.
Note: If the transaction state is Inactive, discard the remaining members of the returned
structure.
Syntax
int tx_info (TXINFO *info);
Parameters
Return Values
• 0 - The cartridge is out of a transaction mode.
• 1 - The cartridge is in transaction mode.
• TX_PROTOCOL_ERROR - The function was called out of context.
• TX_FAIL - Fatal error. The calling cartridge must return WRB_ABORT.
You must call tx_reg() to register at least one resource manager before calling
tx_open(). You must also call tx_open() before calling tx_begin() to begin a
transaction.
Syntax
int tx_open (void);
Parameters
none
Return Values
• TX_OK
• TX_OUTSIDE - The cartridge is not transaction enabled.
• TX_FAIL - Fatal Error. The cartridge must return WRB_ABORT.
See Also
tx_close(), tx_begin().
You must call tx_reg() to register a resource manager before calling tx_open() to
open it. To specify the resource manager, you must pass the name of a database access
descriptor (DAD) defined by your DAD Administration pages.
You may call tx_reg() repeatedly to register several resource managers. When you
subsequently call tx_open(), all the registered resource managers will be opened.
Syntax
int tx_reg() (text *dad);
Parameters
Return Values
• TX_OK
• TX_OUTSIDE - The calling cartridge is not transaction enabled.
• TX_ERROR - The specified DAD is not configured by your DAD Administration
pages.
• TX_FAIL - Fatal Error. The calling cartridge must return WRB_ABORT.
See Also
tx_open().
Syntax
int tx_rollback (void);
Parameters
none
Return Values
• TX_OK
• TX_OUTSIDE - Cartridge not transactions enabled.
• TX_FAIL - Fatal error. The calling cartridge must return WRB_ABORT.
See Also
tx_begin(), tx_commit().
Syntax
int tx_set_transaction_timeout (TRANSACTION_TIMEOUT timeout);
Parameters
→ timeout The time in seconds that a transaction may remain idle before
it is automatically marked for rollback.
Return Values
• TX_OK
• TX_OUTSIDE - The calling cartridge is not transaction enabled.
• TX_ERROR - The function encountered an error in setting the timeout.
• TX_FAIL - Fatal error. The calling cartridge must return WRB_ABORT.
See Also
tx_open().
struct tx_info_t
{
XID xid;
COMMIT_RETURN when_return;
TRANSACTION_CONTROL transaction_control;
TRANSACTION_TIMEOUT transaction_timeout;
TRANSACTION_STATE transaction_state;
};
typedef struct tx_info_t TXINFO;
Field Description
Note: The WRB Transaction Service implementation of the TX interface does not use the
when_return and transaction_control fields.
The Web Request Broker (WRB) API Logger Service allows you to log information to
log files on your local file system or in a database. This information could be related to
a specific instance of a cartridge. You can use the Log Analyzer to extract informative
statistics from this data.
For a description of WRB cartridges and a general overview of the WRB architecture,
see the “Overview of the Web Request Broker (WRB)”.
Logging Guidelines
The default log file location for file system logging is the wrb.log file. Although
cartridges can set their own log files, having a single log file will simplify debugging
and log analysis. Entries in the log file have the following format:
01-14-97 16:33:21 123 pluto LM 12050 7 0x1000 Log Module has been
initialized
Severity Levels
Severity levels range from 0 to 15. The lower the number, the more serious the error.
The logger logs all messages under a specified severity level; for example, if the
severity level is set at 5, messages at severity levels 0 through 4 are logged.
The minimal logging for all cartridges is for all errors (severity <= 3). However, it is
recommended that all warnings are logged as well (severity <= 6).
All cartridge developers should follow the severity level guidelines listed in the
following table to ensure consistent logging.
Soft errors (for example, non- 1 1 indicates that writing to file or resource failed.
fatal input/output errors)
2 (user-defined)
3 (user-defined)
6 (user-defined)
Tracings (for example, request 7 7 indicates the process has entered the init,
has been executed) terminate, or reload stages.
9 (user-defined)
10 (user-defined)
13 (user-defined)
14 (user-defined)
15 (user-defined)
Message Formats
To help administrators read the log file and diagnose errors, it is recommended that
you adopt the message formats listed in this section. There are two different formats:
one for error and warning messages, and one for tracing and debugging messages.
productName–msgNumber: message
Example:
###########message
The product name and message number fields are not included. Instead, the message
is preceded by 11 spaces.
Example:
Syntax
WAPIReturnCode WRB_LOGOpen( dvoid *WRBCtx,
ub4 *logHdl,
WRBLogType type,
WRBLogDestType dest,
text *filename );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_LOGclose(), WRB_LOGwriteMessage(), WRB_LOGwriteAttribute().
Syntax
WAPIReturnCode WRB_LOGWriteMessage( dvoid *WRBCtx,
ub4 logHdl,
text *component,
text *msg,
sb4 severity);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_LOGopen(), WRB_LOGclose(), WRB_LOGwriteAttribute().
Syntax
WAPIReturnCode WRB_LOGWriteAttribute( dvoid *WRBCtx,
ub4 logHdl,
text *component,
text *name,
text *value);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_LOGopen(), WRB_LOGclose(), WRB_LOGwriteMessage().
Syntax
WAPIReturnCode WRB_LOGClose( dvoid *WRBCtx, ub4 logHdl);
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A value of type WAPIReturnCode.
See Also
WRB_LOGopen(), WRB_LOGwriteMessage(), WRB_LOGwriteAttribute().
WRBLogDestType
Indicates the destination for the logged messages. Possible values are the following:
WRBLogType
Indicates whether it is a message or a client attribute.
0 WRBLogSevFatal
1 WRBLogSevErr
4 WRBLogSevWarn
7 WRBLogSevTraItr
8 WRBLogSevAe
11 WRBLogSevDebug
For other severity levels, you can enter the integer values directly.
This chapter describes how to migrate from the obsolete WRB_TXN interface to the
new tx interface.
API Changes
In earlier versions, the Web Application Server supported transactions with the
WRB_TXN interface. In version 3.0, the APIs in that interface have been replaced with
new calls in the tx interface. The following table shows how the obsolete APIs map to
the new APIs.
closeRM tx_close()
beginTransaction tx_begin()
commitTransaction tx_commit()
rollbackTransaction tx_rollback()
transactionInfo tx_info()
setTimeout tx_set_transaction_timeout()
inTransaction tx_info()
annotateURL tx_annotate_url()
annotatePath tx_annotate_path()
Obsolete WRB_TXN API New tx API
registerRM tx_reg()
if (uritype == BEGINTXN) {
WRB_TXNbeginTransaction(WRBCtx);
WRB_TXNregisterRM(WRBCtx, hRM[0]);
WRB_TXNregisterRM(WRBCtx, hRM[2]);
}
}
if (uritype == BEGINTXN)
tx_begin();
}
#include <ocidfn.h>
#include <ocikpr.h>
...
Lda_Def *lda;
sb4 len = -1;
ub1 *hstdef;
...
sqlld2(lda, dad_name, &len);
...
/* to get hstdef for UPI programs */
hstdef = (ubl *)lda->rcsp;
Note that the LDA retrieved from sqlld2 is valid only when a transaction is currently
in progress.
This section describes the WRB APIs in version 2.0, and is provided for users who need
to upgrade their cartridges from 2.0 to 3.0. If you are developing cartridges for Web
Application Server 3.0, you should use the new APIs, which are documented in WRB
Core API Reference.
Note: Currently, you must make all WRBClientRead() calls for a given HTTP request
before your first call to WRBClientWrite().
You can call this function from your Exec function to get the POST data associated with
the current request. This function is especially useful for buffering raw POST data.
If the POST data is in the form of name-value pairs, however, it is usually more
convenient to call WRBGetParsedContent() instead.
Syntax
ssize_t WRBClientRead( void *WRBCtx, char *szData, int nBytes );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes successfully read from the requestor.
See Also
WRBClientWrite(), WRBGetContent(), and WRBGetParsedContent()
Note: Currently, you must make all WRB_walkPBlock() calls for a given HTTP request
before your first call to WRBClientWrite().
You can call this function from your Exec function to send data to a requestor in
response to the current request. You can use this function to send both HTTP data, such
as Content-type: and Set-Cookie: headers, and actual content.
Syntax
ssize_t WRBClientWrite( void *WRBCtx, char *szData, int nBytes );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes successfully written to the requestor.
See Also
WRBReturnHTTPError(), WRBReturnHTTPRedirect(), and
WRBCloseHTTPHeader()
You can call this function from your Authorize or Exec function if you have previously
called WRBReturnHTTPError() or WRBReturnHTTPRedirect() with the close
parameter set to FALSE.
Syntax
ssize_t WRBCloseHTTPHeader( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
The number of bytes successfully written to the requestor.
See Also
WRBReturnHTTPError() and WRBReturnHTTPRedirect()
Syntax
char **WRBGetAppConfig( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the first element in an array of pointers to name-value pairs constituting
the configuration data for the calling cartridge. Each element of the array points to a
character string of the form:
parameter=value
where parameter is the name of a configuration parameter and value is its value. The
array is terminated by a NULL pointer.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBGetConfigVal()
If your cartridge can serve content using more than one character set, your Exec
function can call this function to get a list of the character sets that the requestor
prefers. The Exec function should then choose the first character set in this list in which
your cartridge can generate a response.
Syntax
char *WRBGetCharacterEncoding( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to a comma-separated list of character set identifiers.
See Also
WRBGetLanguage()
You can call this function from your Authorize or Exec function. Usually, Authorize
calls this function to make sure that a requestor issued the current request from a
trusted host.
Syntax
ub4 WRBGetClientIP( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
An IP address in the form of an unsigned 32-bit integer in host byte order, each byte
of which encodes a quad of the IP address.
See Also
WRBSetAuthorization(), WRBGetUserID(), and WRBGetPassword()
You can call this function whenever you need the current value of a configurable
parameter. Your cartridge does not need to maintain local copies of these parameters
in static data or in its application context structure.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
Syntax
char *WRBGetConfigVal( void *WRBCtx, char *name );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the value of the configuration parameter specified by name.
See Also
WRBGetAppConfig()
You can call this function from your Exec function to get the unmanipulated query
string or POST data for the current request.
If your query string or POST data takes the form of name-value pairs, however, such
as when you are processing an HTML form, it’s usually more convenient to call
WRBGetParsedContent() instead.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
Syntax
char *WRBGetContent( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the query string or POST data associated with the current HTTP request.
It returns NULL if the requestor sent no content.
See Also
WRBGetParsedContent()
To get the value of a specific environment variable, it’s usually more convenient to call
WRBGetEnvironmentVariable() or WRBGetORACLE_HOME().
Syntax
char **WRBGetEnvironment( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the first element in an array of pointers to name-value pairs that define the
Web Listener environment. Each name-value pair is a character string that has the
form:
variable=value
where variable is the name of an environment variable and value is its value. The array
is terminated by a NULL pointer.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBGetORACLE_HOME() and WRBGetEnvironmentVariable()
Syntax
char *WRBGetEnvironmentVariable( void *WRBCtx, char *szEnvVar );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the value of the Web Listener environment variable specified by szEnvVar.
It returns NULL if the specified environment variable is not in the Web Listener
environment.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBGetORACLE_HOME() and WRBGetEnvironment()
If your cartridge can serve content in more than one natural language, your Exec
function can call this function to get a list of the languages that the requestor prefers.
Exec should then choose the first language in this list in which your cartridge can
generate a response.
Syntax
char *WRBGetLanguage( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to a comma-separated list of language identifiers.
See Also
WRBGetCharacterEncoding()
Syntax
char *WRBGetMimeType( void *WRBCtx, char *extension );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ extension The filename extension for which you want to get the
corresponding MIME type.
Return Values
A pointer to the name of the MIME type. If the specified filename extension does not
correspond to any MIME type listed in the WRB configuration, WRBGetMimeType()
returns "text/html".
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBGetReqMimeType()
You can call this function from your Exec function to get the value of a specific query
string or POST data entry after first calling WRBGetParsedContent(). This is useful
for parsing HTML forms when you know in advance the names of specific fields.
Syntax
char *WRBGetNamedEntry( char *entryName,
WRBEntry *WRBEntries,
int numEntries );
Parameters
→ entryName The name of the POST data entry of which you want
the value.
Return Values
The value of the parsed content entry specified by entryName. It returns NULL if the
specified entry is not found.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBGetParsedContent() and The WRBEntry Structure
For convenience, a cartridge can store data files, scripts, or other files it needs in the file
system under the ORACLE_HOME directory. This allows the cartridge to store files in a
central place without using hard-coded pathnames. To access the files, you can use the
value returned by WRBGetORACLE_HOME() as a path prefix.
Syntax
char *WRBGetORACLE_HOME( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the value of the ORACLE_HOME environment variable.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBGetEnvironment() and WRBGetEnvironmentVariable()
This function parses this data and passes back an array of pointers to The WRBEntry
Structure structures. Each WRBEntry structure contains the name and value of a POST
data entry. This function also passes back the number of elements in the array.
The pointers passed back refer to WRB application engine memory that your cartridge
should not modify.
If the query string or POST data for a request does not take the form of name-value
pairs, you can call WRBGetContent() instead to get the data in raw form.
Syntax
WRBReturnCode WRBGetParsedContent( void *WRBCtx,
WRBEntry **WRBEntries,
int *numEntries );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
WRBGetParsedContent() returns a value of type WRBReturnCode.
See Also
WRBGetContent(), WRBGetNamedEntry(), and The WRBEntry Structure
You can call this function from your Authorize or Exec function. Your Authorize
function can call this function plus WRBGetUserID() to authenticate the requestor
who issued the current request. Your Exec function might call this function if your
cartridge maintains user accounts.
Syntax
char *WRBGetPassword( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the password. It returns NULL if no password is found.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBSetAuthorization() and WRBGetUserID()
You can call this function in your Exec function to get the MIME type that the requestor
is requesting. You can then use this value to set the MIME type of your response.
Syntax
char *WRBGetReqMimeType( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the MIME type. The returned pointer refers to WRB application engine
memory that your cartridge should not modify.
See Also
WRBGetMimeType()
You can call this function from your Authorize or Exec function. Your Authorize
function, for example, can apply different authorization checks for different URIs.
Your Exec function can call WRBGetURI() to determine how to satisfy the current
request.
Although you can extract the query string for a GET request from its URI , it is usually
more convenient to call WRBGetContent() or WRBGetParsedContent() to do this.
Syntax
char *WRBGetURI( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the URI of the current HTTP request. The returned pointer refers to WRB
application engine memory that your cartridge should not modify.
See Also
WRBGetURL()
Your can call this function from your Authorize or Exec function. Your Authorize
function, for example, can apply different authorization checks for different URLs.
Your Exec function can call this function to determine how to satisfy the current
request.
Although you can extract the query string for a GET request from its URL , it is usually
more convenient to call WRBGetContent() or WRBGetParsedContent() to do this.
Syntax
char *WRBGetURL( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
A pointer to the URL of the current HTTP request. The returned pointer refers to WRB
application engine memory that your cartridge should not modify.
See Also
WRBGetURI()
You can call this function from your Authorize or Exec function. Your Authorize
function can call this function plus WRBGetPassword() to authenticate the requestor
who issued the current request. Your Exec function might call this function if your
cartridge maintains user accounts.
Syntax
char *WRBGetUserID( void *WRBCtx );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
A pointer to the username. It returns NULL if no username is found.
The returned pointer refers to WRB application engine memory that your cartridge
should not modify.
See Also
WRBSetAuthorization() and WRBGetPassword()
You can call this function from any cartridge function to debug your cartridge, and to
keep a log of cartridge transactions.
Syntax
void WRBLogMessage( void *WRBCtx, char *message, int nSeverity );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Value
None.
See Also
Debugging Your Web Cartridge
Note: You must make any WRBReturnHTTPError() call for a given HTTP request before
your first call to WRBClientWrite().
Syntax
ssize_t WRBReturnHTTPError( void *WRBCtx,
WRBErrorCode nErrorCode,
char *szErrorMesg,
boolean close );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ close Specify TRUE if you want to end the HTTP header that
is sent to the requestor.
Specify FALSE if you want to write additional HTTP
header information, such as Set-Cookie: headers,
before completing the HTTP header. You must
subsequently call WRBCloseHTTPHeader() to finish
writing the HTTP header to the requestor.
Return Values
The number of bytes successfully written to the requestor.
See Also
WRBCloseHTTPHeader() and WRBReturnHTTPRedirect()
Note: Currently, you must make any WRBReturnHTTPRedirect() call for a given HTTP
request before your first call to WRBClientWrite().
Syntax
ssize_t WRBReturnHTTPRedirect( void *WRBCtx,
char *szURI,
boolean close );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
→ close Specify TRUE if you want to end the HTTP header that
is sent to the requestor.
Specify FALSE if you want to write additional HTTP
header information, such as Set-Cookie: headers,
before completing the HTTP header. You must
subsequently call WRBCloseHTTPHeader() to finish
writing the HTTP header to the requestor.
Return Values
The number of bytes successfully written to the requestor.
See Also
WRBCloseHTTPHeader() and WRBReturnHTTPError()
Syntax
WRBReturnCode WRBSetAuthorization( void *WRBCtx,
WRBAuthScheme nScheme,
char *szRealm,
boolean bAndOrFlag );
Parameters
→ WRBCtx The pointer to the opaque WRB context object that the
WRB application engine passed to your cartridge
function.
Return Values
WRBSetAuthorization() returns a value of type WRBReturnCode.
Scheme Description
Usage
You can call WRBSetAuthorization() from your Init or Authorize cartridge
function. To set the authentication scheme for your cartridge globally once and for all,
call WRBSetAuthorization() from Init.
To control access to your cartridge in more detail (for example, to assign different
authentication schemes or realms to different URIs), call WRBSetAuthorization()
from Authorize. If you call WRBSetAuthorization()) from both functions, calls
made from Authorize supersede those made from Init.
Note: Both specified schemes must be existing schemes defined in the WRB configuration.
See Also
WRBGetUserID(), WRBGetPassword(), and WRBGetClientIP()
Note: Some WRB API functions return values of type WAPIReturnCode instead. See WRB
Error Codes.
200 OK
201 Created
202 Accepted
204 No Content
401 Unauthorized
403 Forbidden
See Also
WRBReturnHTTPError()
WRBReturnCode (*reload_WRBCallback)();
char *(*version_WRBCallback)();
void (*version_free_WRBCallback)();
WRBReturnCode (*authorize_WRBCallback)();
};
typedef struct WRBCallbacks WRBCallbacks;
G P
GET data parameter blocks 7-46
getting using WRB API 7-27 adding elements to 7-3
copying 7-6
creating 7-7
H cycling through 7-44
deleting elements 7-8
HTTP headers destroying 7-9
retrieving using WRB API 7-36 finding element values in 7-11
returning using WRB API 7-37 finding elements in 7-10
getting elements 7-32
getting number of elements 7-33
I getting the first element 7-12
performance
ICX Service
checking using WRB API 7-43
APIs 9-1
POST data
authenticating requests 9-11
retrieving using WRB API 7-27, 7-35
creating requests 9-3
destroying requests 9-4
example 5-1
getting header information 9-7, 9-9 R
getting more data 9-5 Reload function 2-16
getting request information 9-8 repositories
proxy settings 9-15, 9-16 closing 8-3
sending content data 9-12 closing documents in 8-5
sending header data 9-13 destroying documents in 8-6
setting request method 9-14 getting attributes of documents in 8-7
submitting requests 9-10 listing documents in 8-14
Init function 2-11 opening 8-2
opening documents in 8-4
reading documents in 8-11
L setting attributes of documents in 8-10
updating documents in 8-13
listener
writing to documents in 8-12
getting information using WRB API 7-21
Logger Service
APIs 11-1