| Lescasse Consulting |
| Home Company News Prices Download Buy Forums |
|
|
Deploy your APL+Win Application on the Web
Download the Sample OWC.W3 workspace Load this article sample APL application in your browser and play with it! (please be patient: this may easily take 30 seconds) Introduction This is the second part of a 2 parts article about the new APL2000 APL+WebComponent product which allows you to publish your APL+Win applications on the Web. The first part "APL+Web Component (part 1)" introduced this new technology basics and showed how to setup and port a very small APL+Win application to the Web. In this article we will go further within the technology and port to the Web the following APL+Win application:
This application displays the various tasks of a Project with a diagram in an OWC (Microsoft Office Web Component) spreadsheet. One can click on the Add Task button to add a new task to the Project:
Clicking the Add button in the above screen will add the Project Step 10 task to the project and clicking on the Display Project button computes and displays the new Project diagram after sorting the tasks according to their start date:
To delete a task, one can click on the Delete Task button resulting in the following frame to be displayed:
Select a line by clicking on the line number and then click Delete to delete the task. Clicking Display Project would compute and display the new Project diagram with the task having been deleted.
Downloading and installing the Microsoft OWC Spreadsheet For this application we will need to use the Microsoft OWC Spreadsheet. This ActiveX object is just a simplified version of Excel especially made by Microsoft for use in the browser, but since it is an ActiveX object, we can also use it within any APL+Win application. You can download the Microsoft Office Web Components v11 which work with Office 2003 from the Microsoft Web Site. Be sure to select the right language corresponding to your Office language (the previous link is for the "English" version of OWC). To install it, just run the OWC11.EXE file you have downloaded. (Note: if the previous link has changed, start Google.com and search for: "owc11.exe" and "microsoft") Alternatively you can download the Microsoft Office Web Components v10 which work with Office 2002 from the Microsoft Web Site. Be sure to select the right language corresponding to your Office language (the previous link is for the "English" version of OWC). To install it, just run the OWC10.EXE file you have downloaded. Note: if this link has changed, start Google.com and search for: "owc10.exe" and "microsoft" Note that the Microsoft Office Web Components do not only contain a Spreadsheet object, but also a Charting object and a Database object for publishing graphics or data on the Web. Finally, if you want to learn how to program the OWC Spreadsheet, there is nothing better than downloading and installing the Microsoft Office Web Components Toolpack.
Preparing the workspace This application will be called owc so we have created an C:\INETPUB\WWWROOT\LC\WEBSERVICES\OWC.W3 workspace containing all the application functions. Then we have (p)copied the C:\INETPUB\WWWROOT\LC\WEBSERVICES\APLWS.W3 workspace into C:\INETPUB\WWWROOT\LC\WEBSERVICES\OWC.W3 and saved C:\INETPUB\WWWROOT\LC\WEBSERVICES\OWC.W3 again. Let's remember that APLWS.W3, as delivered by APL2000, contains the various base functions necessary for APL+WebComponent to work. Our OWC.W3 workspace is made of 2 functions which we will publish:
and we will develop a bunch of other APL functions which will all run on the Server:
We will soon explain why we decide to run all these functions on the Server rather than publish them to run in the browser.
Setting up the Web Services with APL+WebServicesController Rather than going through all the steps (a bit cumbersome) necessary to set up our APL application within the AWS Admin application (the APL Web Services Configuration console), we will use the new APL2000 APL+WebServicesController product to programmatically run all the setup steps. APL+WebServicesController is a COM object and therefore we can use APL+Win to pilot it as wished. You can download the Alpha version of APL+WebServicesController from the APL2000 Site (you need to be an APLDN Subscriber and a Login and Password is required). Here is the APL+Win Script which sets up the Workspace and the Web Server for our owc application:
’ CreateOwcServer;Z
[1] ©’ CreateOwcServer -- Uses the new APL+WebServicesController COM object to setup the Web Server
[2] ©’ (c)2004 Eric Lescasse
[3]
[4] :if 0¹½'wsc'Œwi'self'
[5] Z„'wsc'Œwi'Create' 'APL2000.WSC'
[6] :end
[7] Z„'wsc'Œwi'serviceStop'
[8]
[9] © Delete Server & Workspace if already exist
[10] Z„'wsc'Œwi'DeleteWorkspace' 'owc'
[11] Z„'wsc'Œwi'DeleteServer' 'owc'
[12]
[13] © Setup new Server
[14] Z„'wsc'Œwi'newServer' 'owc'
[15] Z„'wsc'Œwi'setServerHost' 'owc' 'localhost'
[16] Z„'wsc'Œwi'setServerPort' 'owc' '4000'
[17] Z„'wsc'Œwi'setServerPublicHttpDir' 'owc' 'c:\inetpub\wwwroot\lc\webservices'
[18] Z„'wsc'Œwi'addServerDefaultFileName' 'owc' 'default.htm'
[19] Z„'wsc'Œwi'setEnableDefaultFile' 'owc' 1
[20]
[21] © Setup new Workspace
[22] Z„'wsc'Œwi'newWorkspace' 'owc'
[23] Z„'wsc'Œwi'modifyWorkspaceMaxpool' 'owc' '4'
[24] Z„'wsc'Œwi'modifyWorkspaceDebug' 'owc' '1'
[25] Z„'wsc'Œwi'modifyWorkspaceLocation' 'owc' 'c:\inetpub\wwwroot\lc\webservices\owc.w3'
[26]
[27] © Create and setup new Virtual Directory
[28] Z„'wsc'Œwi'newVirtualPath' 'owc' '/jsaveservice/service1.asmx'
[29] Z„'wsc'Œwi'modifyServerPathWsid' 'owc' '/jsaveservice/service1.asmx' 'defaultworkspace' 'owc'
[30] Z„'wsc'Œwi'modifyServerPathFunction' 'owc' '/jsaveservice/service1.asmx' 'default' 'HTTP_SoapProcess'
[31] Z„'wsc'Œwi'addServerPathRargData' 'owc' '/jsaveservice/service1.asmx' 'header' 'header'
[32] Z„'wsc'Œwi'addServerPathLargData' 'owc' '/jsaveservice/service1.asmx' 'data' 'entity-body-utf8'
[33] Z„'wsc'Œwi'modifyServerPathResultData' 'owc' '/jsaveservice/service1.asmx' 'r' 'r' 'content-type'
[34] Z„'wsc'Œwi'addServerPathResultData' 'owc' '/jsaveservice/service1.asmx' 'r2' 'soap-envelop-start'
[35] Z„'wsc'Œwi'addServerPathResultData' 'owc' '/jsaveservice/service1.asmx' 'r3' 'soap-body'
[36] Z„'wsc'Œwi'addServerPathResultData' 'owc' '/jsaveservice/service1.asmx' 'r4' 'soap-envelop-end'
[37]
[38] © Create and setup new Virtual Directory
[39] Z„'wsc'Œwi'newVirtualPath' 'owc' '/owc/xmlfile'
[40] Z„'wsc'Œwi'modifyServerPathWsid' 'owc' '/owc/xmlfile' 'defaultworkspace' 'owc'
[41] Z„'wsc'Œwi'modifyServerPathFunction' 'owc' '/owc/xmlfile' 'default' 'GetXMLFile'
[42] Z„'wsc'Œwi'addServerPathRargData' 'owc' '/owc/xmlfile' 'filename' 'entity-body'
[43] Z„'wsc'Œwi'modifyServerPathResultData' 'owc' '/owc/xmlfile' 'r' 'r' 'document-filename'
[44] Z„'wsc'Œwi'addServerPathResultData' 'owc' '/owc/xmlfile' 'r2' 'document-filename-delete'
[45]
[46] © Start Workspace and Server
[47] Z„'wsc'Œwi'serviceStart'
[48] Z„'wsc'Œwi'startWorkspace' 'owc'
[49] Z„'wsc'Œwi'startServer' 'owc'
’
After having properly installed the APL+WebServicesController (you just need to run the APLWSCSetup.msi installer) run the CreateOwcServer function:
CreateOwcServer
This will result in the following setup added to the AWS Admin console:
and:
with the following parameters:
Publishing the necessary functions with JSAVESDK As done for the Demo application in APL+WebComponent (part 1):
And we are now ready to use the application in the browser!
Using the OWC application in the browser Start an instance of Internet Explorer and enter the following URL: http://localhost:4000/owc.htm Here is how it looks:
This application is resizable and works exactly the same in the browser as when you start it as a Windows application.
Analyzing the application code First let's display the 2 published functions: AutoStart and Main. Let's analyze the AutoStart function first.
’ AutoStart;dir;Z
[1] is‘browser„'APL+Js'Œsysid
[2] :if is‘browser
[3] Main''
[4] :else
[5] AutoStartServer
[6] :end
’
’ AutoStartServer;dir;Z
[1] :if 0'#'Œwi'server'
[2] Main''
[3] :else
[4] Œ„'I am running on the server!'
[5] © Change Œchdir from C:\Windows\System32 (the default for a COM server) to the workspace dir
[6] dir„²Œwsid
[7] dir„²(~^\dir¬'\')/dir
[8] Z„Œchdir dir
[9] :endif
[10]
’
We have also displayed the AutoStartServer function which is called by AutoStart. Let's comment first about AutoStart. In AutoStart we first check Œsysid and compare it to 'APL+Js': as a matter of fact Œsysid is a way to know if the workspace is run in the browser (Œsysid is 'APL+Js' in this case) or on the Server (Œsysid is 'APL+Win' in that case). We set a variable is‘browser to 1 if we are running in the browser. We will need this information in the Main function. So, if the workspace is run in the browser (i.e. if it is the JScript translated version of the APL code which runs), then we execute Main'' which builds the application interface and displays the Project form in the browser. On the other hand, if is‘browser is 0, this means that we are not running in the browser and this can occur in 2 cases:
The most important part of this application is of course the Main function:
’ Main B;Z;height;width;off;M;H;arg;warg;bool;dir;file;colorsmat;tasks;spreadcols;lastcol;range;I;J;res;range2;
Let's explain this function in detail. First, it is built on a :select ... :case ... structure. When the Main argument is an empty character vector, lines 5 to 46 are executed and the application main form is built. The interface is made of 3 frames and 3 buttons. Only one of the 3 frames may be visible at any time: the other 2 are hidden. The 3 buttons help show the appropriate frame and hide the other 2. In 2 of the frames an OWC Spreadsheet object is instanciated. Note that in order for the OWC Spreadsheet object (which is an ActiveX object) to get displayed in the browser we need to instanciate it using its class id:
'fmProject.owc' Œwi 'Create' '{0002E551-0000-0000-C000-000000000046}'
In order to keep all the code within the Main function, we embed all the necessary handlers within it. For example when a user clicks on the bnProj button in the main form, the following handler is run:
Main"bnAdd.onClick"
so the Main function is called with an argument of bnAdd.onClick and the :select control structure branches to line 94 and executes lines 95 to 97. This technique makes the code very readable. Events which we handle here are the onClick events on the various buttons, but also the onResize events on the main form and on the Frame objects. This way our form may be resized by the user (even in the browser) and all controls get nicely resized or repositionned accordingly. Another point to notice is that we needed to run a few subroutines to perform specific tasks like FillTasks (to fill the OWC Spreadsheet in the Delete Task frame) or DisplayProject (to compute and display the Project graph). Rather than making these subroutines, we have made them methods of the Main function by encapsulating them as :casestatements in the Main function: this way Main contains all the logic necessary to its operation, except for the code sections which need to run on the Server.
The Client Server decisions and RunAtServer One of the difficulties you'll bump into when porting APL applications to the Web will be to decide which lines of your code need to run on the Server and which should run on the Client. But first let's explain a little bit more what running on the Client and running on the Server mean. Every function you have published with JSaveSDK will run on the Client (after having been translated by JSaveSDK to JScript): however your application is installed on a Server and is loaded by APL+Win on the Server when someone starts it in his browser. APL functions which are not published will run on the Server. In general you are publishing the APL functions which create your application interface and are the main functions of your application: however these functions may call subroutines which you want or need to run on the Server. The way to do that is to call these functions through the following utility:
’ R„RunAtServer R
’
Here is an example: in our OWC application, we need to use an APL+Win file to store the Project tasks information. Using the file system is not authorized on the Client side for obvious security reasons, therefore we need to open the file on the Server (in any case, most often, a file like the file containing the Project tasks information has to be shared among Web users so it needs to reside on the Server). To open the file (which we called OWC.SF) we need to write a TieFile utility and make it run on the Server. Here is how we call it:
Z„RunAtServer TieFile 0
and here is the TieFile function which opens (or creates) the OWC.SF file:
’ R„TieFile dummy;M;H;bool;dir;file;Z;comp2
[1]
[2] R„0 0½''
[3]
[4] dir„Œchdir''
[5] file„dir,'\owc'
[6]
[7] © Create or tie the OWC file
[8] :if FileExist file,'.sf'
[9] file Œfstie 1
[10] :else
[11] comp2„'File Structure',Œtcnl
[12] comp2„comp2,Œtcnl,'Comp 1 -- File Description'
[13] comp2„comp2,Œtcnl,'Comp 2 -- File Structure'
[14] comp2„comp2,Œtcnl,'Comp 3-10 -- (reserved)'
[15] comp2„comp2,Œtcnl,'Comp 11 -- Tasks matrix'
[16] comp2„comp2,Œtcnl,' [;1] „… Task #'
[17] comp2„comp2,Œtcnl,' [;2] „… Task Name'
[18] comp2„comp2,Œtcnl,' [;3] „… Task Start Date'
[19] comp2„comp2,Œtcnl,' [;4] „… Task End Date'
[20] comp2„comp2,Œtcnl,' [;5] „… Task % Progress'
[21] file Œfcreate 1
[22] Z„'APL+Web Components Project Demo Application File'Œfappend 1
[23] Z„comp2 Œfappend 1
[24] Z„(›'')Œfappend¨8½1
[25] Z„(0 5½0''0 0 0)Œfappend 1
[26]
[27] :end
[28]
’
Note that the above function describes the file structure we are using for our very simple OWC.SF application file. The rules are the following:
In our case, the TieFile function did not need any argument or to return any result, but we still had to add an argument and a result in its syntax; to conform to the above rule. The argument to a function called through RunAtServer may be a nested vector and its result may also be a nested vector. Look at the various lines in the Main function (displayed above) which call RunAtServer to run subroutines on the Server. Line 125 shows an example of passing a nested vector to a function called through RunAtServer. [113] Z„RunAtServer AddTask name start end progress So, the big question is: "when do we need to use RunAtServer and when not?" Here are a few hints to help you make these decisions:
To better explain this last point, here is an example: we needed to write an AddTask function and to run it on the Server to add a new task to our OWC.SF since this operation uses a file. It would have been an error to try to read the data input by the Web User within the AddTask function. This is easy to understand: the Server does not know about what the Client has done in its browser. Instead we needed to read the data input by the Web User within the Main function (which runs on the Client) and to pass these information to the AddTask function, hence the following code in the Main function: [113] :case'frAdd.bnAdd.onClick' [114] © Read screen data [115] name„'fmProject.frAdd.edName' Œwi 'text' [116] start„'fmProject.frAdd.edStart' Œwi 'text' [117] start„(†¨Œfi¨(start¬'/')›start)[3 1 2] [118] start[1]„2000+100|start[1] [119] start„100ƒstart [120] end„'fmProject.frAdd.edEnd' Œwi 'text' [121] end„(†¨Œfi¨(end¬'/')›end)[3 1 2] [122] end[1]„2000+100|end[1] [123] end„100ƒend [124] progress„†Œfi,'fmProject.frAdd.cbProgress' Œwi 'text' [125] errmsg„RunAtServer AddTask name start end progress [126] :if 0¹½errmsg [127] 'fmProject.frAdd.edName' Œwi 'text' '' [128] 'fmProject.frAdd.edStart' Œwi 'text' '' [129] 'fmProject.frAdd.edEnd' Œwi 'text' '' [130] 'fmProject.frAdd.cbProgress' Œwi 'text' '' [131] 'fmProject.frAdd.lStatus' Œwi '‘style_color' '#00AA00' [132] 'fmProject.frAdd.lStatus' Œwi 'caption' 'Record added to the database!' [133] :else [134] 'fmProject.frAdd.lStatus' Œwi '‘style_color' '#FF0000' [135] 'fmProject.frAdd.lStatus' Œwi 'caption' errmsg [136] :end And here is the AddTask function which runs on the Server:
’ R„AddTask rarg;name;start;end;progress;tasks;startdate;enddate
[1] ©’ R„AddTask rarg -- Adds a task to the OWC file
[2]
[3] R„''
[4] (name start end progress)„rarg
[5] (startdate enddate)„Œsplit³10000 100 100‚start end
[6] :if~DATECHECK startdate ª R„'Invalid Start Date! ' ª :end
[7] :if~DATECHECK enddate ª R„R,'Invalid End Date! ' ª :end
[8] :if startdate[1]¬2004 ª R„R,'Start year must be 2004! ' ª :end
[9] :if enddate[1]¬2004 ª R„R,'End year must be 2004! ' ª :end
[10] :if start>end ª R„R,'Start date must be before end date! ' ª :end
[11] :if 0¹½R
[12] tasks„Œfread 1 11
[13] tasks„tasks®(1+—/0,tasks[;1])name start end progress
[14] tasks Œfreplace 1 11
[15] :end
’
In the AddTask function we check the Start date and End date entered on the client and the AddTask function returns an appropriate error message if any of these dates is not valid for our application. if the dates are valid, we can add the task to the OWC.SF file: this is done on lines 12 to 14. In the frAdd.bnAdd.onClick event handler, we capture the result of AddTask in the errmsg variable and depending on its content we display an error message in the Add Task frame or inform the user that the record has indeed be added to the database, in chich case we empty the Add Task frame fields. One interesting point about the frAdd.bnAdd.onClick handler is that we have used a DHTML style property to set the Status label color. This is done as follows:
'fmProject.frAdd.lStatus' Œwi '‘style_color' '#FF0000'
Note that you can use any style, DHTML or JScript property on interface objects
as long as you set them as APL User defined properties starting with the ‘style_ prefix,
followed by the style name (example: ‘style_fontFamily , ‘style_fontSize , ‘style_backgroundColor ,
etc.). Note that the value you pass to the property should be a valid value
for the DHTML or JScript property, hence the '#FF0000' for
the color style here. Using the OWC Spreadsheet on the Client and on the Server As I said, not all OWC Spreadsheet properties and methods work on the Client when translated to JScript. However a few of them work fine. In our OWC application, we have used the OWC Spreadsheet both on the Client and on the Server. Using the OWC Spreadsheet on the Client Let's first talk about using it on the Client. Look at the FillTasks method which role is to fill the OWC Spreadsheet in the Delete Task Frame with our tasks' nested array so that the User may select a task to delete:
[133] :case'FillTasks'
[134] tasks„RunAtServer Fread 1 11
[135] :for I :in 1+1†½tasks
[136] :for J :in ¼¯1†½tasks
[137] range„(Jœ'ABCDE'),•I
[138] Z„'fmProject.frDel.owc' Œwi ('ActiveSheet.Range("',range,'").Value2') ('')
[139] :end
[140] :end
[141] :for I :in ¼1†½tasks
[142] :for J :in ¼¯1†½tasks
[143] range„(Jœ'ABCDE'),•I
[144] Z„'fmProject.frDel.owc' Œwi ('ActiveSheet.Range("',range,'").Value2') (•tasks[I;J])
[145] :end
[146] :end
We first need to read the tasks nested array from the OWC.SF file on the Server, which is done through a small trivial Fread utility:
’ R„Fread A
[1] R„•¨Œfread A
’
(note that we are making each cell a string with the •¨ construct to avoid having to do that on the Client side) Then we perform 2 double loops on the Client side:
The reasons we have had to do these loops is that the OWC Spreadsheet Clear method which was supposed to work on a range of cells did not work when translated through JSaveSDK and similarly the Value2 property which normally accepts a nested array to fill a matrix range of cells at once, would not work either when translated through JSaveSDK. So here is a case where things were not working as expected when translated to JSaveSDK, but where we still could find a workaround to make things work on the Client side. Obviously these loops do not provide us with the best performance possible, especially since JScript is rather slow. Using the OWC Spreadsheet on the Server Let's talk now about using the OWC Spreadsheet on the Server side. You will tell me: what? this is an interface problem and should be running on the Client: how can you make this running on the Server side? Well, this part is the trickiest in our example, but shows what you can do with APL+WebComponent. First look at the code which runs in the Main function when computing and displaying a new Project graph: [122] :case'DisplayProject' [123] Z„RunAtServer ComputeProject is‘browser [124] (rok data)„Z [125] :if rok = 0 [126] :if is‘browser [127] 'fmProject.owc' Œwi 'xXMLUrl' data [128] :else [129] 'fmProject.owc' Œwi 'xXMLData' data [130] :endif [131] :endif Basically almost everything is done on the Server in a ComputeProject function (displayed a little further below). We need a function to run on the Server for several reasons here:
Here is the ComputeProject function:
’ R„ComputeProject is‘browser;tasks;mindate;maxdate;spandates;boolmat;totals;splitmat;daysmat;
The ComputeProject function contains 3 parts:
So let's look at the DisplayProject method in the Main function: [122] :case'DisplayProject' [123] Z„RunAtServer ComputeProject is‘browser [124] (rok data)„Z [125] :if rok = 0 [126] :if is‘browser [127] 'fmProject.owc' Œwi 'xXMLUrl' data [128] :else [129] 'fmProject.owc' Œwi 'xXMLData' data [130] :endif [131] :endif It runs ComputeProject on the Server with an argument of is‘browser (which is 1). The ComputeProject function returns the following string to the client data variable:
'http://localhost:4000/owc/xmlfile?',filename
where filename is the name of the XML file created on the server. Then if the ComputeProject return code is 0 and if we run on the Client , we pass data as an argument to the Client OWC Spreadsheet xXMLUrl property . This results in the Client OWC Spreadsheet downloading the right XML file from the Server and instantaneously populating itself with its content. As a summary, to use the OWC Spreadsheet on the Server rather than on the client, we have:
Note that using a result of r2 document-filename-delete in the /owc/xmlfile setup results in the native XML file being deleted as soon as it has been received by the Client. This avoids the Server to soon get cluttered with XML native files created by people using our application. This is very important: we should never forget that such an application runs on Internet and that there may be thousands of people using it everyday (or more): this would quickly result in tens of thousands of XML files cluttering the Server! Yes I know: all this may seem a bit complicated at first, but it works and rather efficiently!
The APL+WebComponent development cycle How do you proceed in practice to write an APL+WebComponent application? Well this depends if you are writing a brand new application or trying to port an existing APL+Win application to the Web. Assume first you are writing a brand new APL+Win application to be published on the Web. I recommend the following development cycle:
If you are trying to port an existing APL application, things are more complicated,
because you'll be inclined to try to use your existing code as is and to publish
it as is to go faster. It's almost sure you'll get some headaches
doing that.
Debugging an APL+WebComponent application This may be very tricky to do. First let's forget about debugging stuff on the Server side of your application: remember: the Server side is pure APL+Win and you know how to debug pure APL programs. On the Client side it is more complex. The reason is that you do not always get a clear error message pointing you to the error. Sometimes you get no error message, but things do not happen in the browser while they were happening when testing in APL mode. Sometimes you get an Internet error but it is not explicit enough to let you know where something bumped. Here is an example:
Sometimes you get an APL Error popping up in the browser, but the reported error is further on in the program than the one that really occured. Sometimes things are due to your coding because you forgot about some of the JSaveSDK limitations (always keep at hand the following document and always refer to it: description of JSaveSDK supported and unsupported APL features). But sometimes things are due to bugs in the JSaveSDK translation system (i.e. you do everything right and your application still does not run as expected). Fortunately, there aren't many of these, but as for any software, that may happen. Let's assume I have made an error in the frAdd.bnAdd.onClick handler, as follows: [113] :case'frAdd.bnAdd.onClick' [114] © Read screen data [115] name„'fmProject.frAdd.edName' Œwi 'text' [116] start„'fmProject.frAdd.edStart' Œwi 'text' [117] start„(†¨Œfi¨(start¬'/')›start)[3 1 2] [118] start[1]„2000+100|start[1] [119] © start„100ƒstart © correct line [120] start„ƒstart © intentional error: left ƒ argument omitted [121] end„'fmProject.frAdd.edEnd' Œwi 'text' [122] end„(†¨Œfi¨(end¬'/')›end)[3 1 2] [123] end[1]„2000+100|end[1] [124] end„100ƒend [125] progress„†Œfi,'fmProject.frAdd.cbProgress' Œwi 'text' [126] errmsg„RunAtServer AddTask name start end progress [127] :if 0¹½errmsg [128] 'fmProject.frAdd.edName' Œwi 'text' '' [129] 'fmProject.frAdd.edStart' Œwi 'text' '' [130] 'fmProject.frAdd.edEnd' Œwi 'text' '' [131] 'fmProject.frAdd.cbProgress' Œwi 'text' '' [132] 'fmProject.frAdd.lStatus' Œwi '‘style_color' '#00AA00' [133] 'fmProject.frAdd.lStatus' Œwi 'caption' 'Record added to the database!' [134] :else [135] 'fmProject.frAdd.lStatus' Œwi '‘style_color' '#FF0000' [136] 'fmProject.frAdd.lStatus' Œwi 'caption' errmsg [137] :end I have changed line 119 by line 120 which contains an obvious error (no left argument to the decode primitive). If we republish and test/run the application in the browser we get the following error:
Conclusion In this second article on APL+WebComponent we have showed a much more sophisticated APL application ported to the Web. If you try this application, please note that it has not been written to handle limit conditions like deleting all tasks, or creating tasks with an end date so far away that it will go beyond the number of columns contained in the OWC Spreadsheet object, etc. If you try the owc application, don't try to break it please. We have explained how to use the APL+WebServicesController to automate
setting up your APL+Web Component application, how to develop such an application,
how to separate code which needs to run on the Client and code which needs
to run on the Server, how to make code run on the Server, how to use the Microsoft
OWC Spreadsheet, how to sometimes do interface work on the Server and transfer
it to the Client. If you succeed or if you need help, please let me know. Note: please check this page again soon, since I plan to update it with more information! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| This entire Web site has been dynamically generated by APL+Win Objects™ 6.0 For all questions contact: info@lescasse.com Copyright © 2003-2005 Lescasse Consulting. All rights reserved. |