Internet Technologies:cxp

Standalone CXP Foundation

Standalone CXP refers to the ability of Xbase++ to use a HttpEndpoint()for servicing your CXP requests in addition to RESTful API calls using a WebHandler(). The benefits of this scenario are outlined in the following:

- Simple setup. Just start the Xbase++ executable and your application is ready for handling CXP requests.

- Faster response times since there is no web server or FastCGI gateway involved

- Super easy integration: you can add a CXP endpoint to your existing point-of-sales solution and this way support the mobile devices used by your service personnel.

An illustration about the relationship of the CXP infrastructure and HttpEndpoints is shown below.

1 Your browser or any other HTTP client, for example, an Xbase++ HttpClient()object tries to access a resource via an URI. The client finds the host, which in our case is the machine which runs the Xbase+++ process with a HttpEndpoint.

2 The HttpEndpoint receives the request and forwards all URIs ending with .cxp to a cxp-worker thread. All other requests are routed to the proper processor depending on the URI. Typically, this is a Webhandler.

3 The cxp-worker thread finally receives the request, checks if all resources and binaries are available and executes the :render() method of the CXP page.

4 If the resources are not available, the cxp-worker spawns the cxc-builder to transpile/compile and link the binaries of the CXP page. Note that in such cases, the loading of the CXP page binaries also leads to a :load() method invocation.

5 After the cxp-worker has processed the request, it returns the generated content, the HTTP protocol status code as well as a status text via the HttpEndPoint to the requesting HTTP client.

Setting up standalone CXP

In order to use CXP inside your applications, you need to set up a HttpEndpoint for receiving incoming requests. By default, a HttpEndpoint forwards all requests to a set of preconfigured processors, including WebHandlers and WebSocketHandlers. For servicing CXP requests, however, we need to extend the HttpEndpoint sligthly. Fortunately, this is very easy since all web technologies share the same unified web platform in Xbase++. We simply need to add a CXP processor to the HttpEndpoint and add a litte configuration code. Afterwards, the end point can process CXP pages right away.

For simplicity, the following code implements a CxpEndpoint class which is derived from HttpEndpoint which starts an end point for serving CXP pages located in the current directory of the process. This directory is considered the document root.

// Required to link CXP to our application 
// 
#pragma library("cxpcore10.lib") 
REQUEST CxpApplication 

#define PORT 81 

/// <summary> 
/// First, we create a test CXP page and save it to disk. Then, we start 
/// up the CxpEndpoint. Afterwards, the URI: http://localhost:PORT/hello.cxp 
/// entered in a browser shows us our hello world. 
/// </summary> 
PROCEDURE main 
LOCAL cPort 
LOCAL oHttp 
LOCAL cHtml 
LOCAL lStarted 

cPort := Var2Char(PORT) 

TEXT INTO cHtml WRAP 
<!DOCTYPE html> 
<html> 
 <body> 
 <h1>Hello World from @(AppName())</h1> 
 <p>Today is @(Date())</p> 
 </body> 
</html> 
ENDTEXT 

MemoWrit("hello.cxp",cHtml) 

oHttp := CxpEndpoint():new( PORT, "localhost" ) 
lStarted := oHttp:start() 
IF .NOT. lStarted 
  ? "Startup error. Check if port "+cPort+" is already in use." 
  WAIT 
  RETURN 
ENDIF 

? "http://localhost:"+cPort+"/hello.cxp" 
WAIT 
RETURN 

/// <summary> 
/// Implement a CxpEndpoint class which adds the 
/// CXP processor and handles default configuration 
/// </summary> 
CLASS CxpEndpoint FROM HttpEndpoint 
EXPORTED: 
METHOD defaultProcessors() 
METHOD defaultConfig() 
ENDCLASS 

/// <summary> 
/// We simply add the CxpProcessor to the array of 
/// default processors of this end point. 
/// </summary> 
METHOD CxpEndpoint:defaultProcessors() 
LOCAL aRet 
aRet := SUPER:DefaultProcessors() 
AAdd( aRet , "CxpProcessor" ) 
RETURN( aRet ) 

/// <summary> 
/// We need to ensure the FOXCDX DBE is available. 
/// This is a requirement of the CXP storage manager. 
/// We then use DataObjects to return default 
/// configuration data for the CXP processor. 
/// </summary> 
METHOD CxpEndpoint:defaultConfig(cToken) 
LOCAL oDO := DataObject():New() 

IF !("CDXDBE" $ dbelist()) 
  DbeLoad("CDXDBE") 
ENDIF 
IF !("FOXDBE" $ dbelist()) 
  DbeLoad("FOXDBE") 
ENDIF 
IF !("FOXCDX" $ dbelist()) 
  DbeBuild("FOXCDX","FOXDBE","CDXDBE") 
ENDIF 

cToken := Lower(AllTrim(cToken)) 
IF cToken=="session" 
  oDO:Provider := "CxpCookieSessionManager" 
  oDO:Timeout  := 15 
ELSEIF cToken=="storage" 
 oDO:Provider := "AppStorageManager" 
 oDO:Store    := "cxp-data\application-storage.dbf" 
ENDIF 
RETURN( oDO ) 

CxpInstallRoot: By default, CXP is installed on your development machine in the folder \program files\alaska software\cxp20. However, when deploying on a customer site you need to deploy CXP alongside with your Xbase++ application. To do this, install the complete cxp20 directory from your development machine at your customer site. Afterwards, set the following environment variable for telling the CXP processor where to find the cxc-builder:

SET CxpInstallRoot=<your install location>\cxp20\ 

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.