HAHTsite IDE Programming Guide

Size: px
Start display at page:

Download "HAHTsite IDE Programming Guide"

Transcription

1 HAHTsite IDE Programming Guide

2 IDE Programming Guide release 4.0

3 Notice Copyright 1999 HAHT Software, Inc. All Rights Reserved May 1999 MN07-C No part of this publication may be copied, photocopied, reproduced, transmitted, transcribed, or reduced to any electronic medium or machine-readable form without the prior written consent of HAHT Software, Inc. Information in this document is subject to change without notice. Names and information used in examples are fictitious. U.S. GOVERNMENT RESTRICTED RIGHTS. It is acknowledged that the Software and the Documentation were developed at private expense, that no part is in the public domain, and that the Software and Documentation are Commercial Computer Software provided with RESTRICTED RIGHTS under Federal Acquisition Regulations and agency supplements to them. Use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer Software clause at DFAR et. seq. or subparagraph (c)(1) and (2) of the Commercial Computer Software 96 Restricted Rights at FAR , as applicable. Contractor is HAHT Software, Inc., 4200 Six Forks Road, Raleigh, NC Rights are reserved under copyright laws of the United States with respect to unpublished portions of the Software. Trademarks HAHT, HAHT Software, HAHTsite, e-scenario, and e-nable your enterprise are trademarks or U.S. registered trademarks of HAHT Software, Inc. Portions Copyright Summit Software Company. This product includes software developed by the Apache Group for use in the Apache HTTP server project ( Any other corporate names, product names, tradenames, trademarks, service marks, or service names owned or registered by any other company and mentioned herein are the property of their respective companies. Specifications subject to change without notice. HAHT Software, Inc Six Forks Road Raleigh, NC USA (919) (888) (in the USA) (919) (Technical Support)

4 Contents About This Book Who is this book for? xvii Conventions xvii Other HAHTsite documentation xviii Other HAHTsite products xix HAHT Software s commitment to you xix 1 Introduction Overview HAHTsite Server Object Model The project package The datamanager package The form package The access package The corba package Data-management API ActiveX Data Objects classes Relationship between ADO and SOM classes Data management in HAHTtalk Basic projects Client-side scripting CORBA capabilities Access to COM/DCOM objects Remote debugging Working with Java Projects What s in this chapter Adding server-side code to a Java project iii

5 Contents HAHTsite Server Object Model External logic In-line code Invoking an expression or a method from a dialog box Adding code in Server-side Code view What s in a Java page? Editing HahtApplication.java and HahtSession.java Adding Java files to a project Naming conventions for Java projects Naming conventions for dynamic pages Calling a dynamic page from Java Event handling in a Java project Editing and compiling Java code Using the code editor Compiling a Java application Finding compile-time errors Debugging a Java application Working with application directories Java options Changing the Java file type Overriding Java compiler options Overriding options for JAR, CAB, and ZIP files Working with HAHTtalk Basic Projects What s in this chapter Adding server-side code to a HAHTtalk Basic project HAHTsite Server Object Model External logic In-line code Invoking an expression or a subroutine from a dialog box Adding code in Server-side Code view What s in a HAHTtalk Basic page? Adding HAHTtalk Basic files to a project Naming conventions for HAHTtalk Basic projects Include files and Globals.hbs iv

6 Contents Project and external includes Declaring public variables with Globals.hbs Precompiler directives Calling dynamic pages from HAHTtalk Basic Event handling in a HAHTtalk Basic project Editing and compiling HAHTtalk Basic code Using the code editor Compiling a HAHTtalk Basic application Finding compile-time errors Debugging a HAHTtalk Basic application Working with application directories Comparing HAHTtalk Basic and Visual Basic HAHTtalk Basic data types Subroutines and functions File I/O Error handling Code page properties Calling Server-side Java from HAHTtalk Basic Introduction Using Java objects with HAHTtalk Basic CreateJavaObject GetJavaClass CreateTypedJavaNull Differences between HAHTtalk Basic and Java Java is strongly typed Parameter passing Java is case sensitive Locating objects Mapping HAHTtalk Basic types to Java parameter types Mapping Java types to HAHTtalk Basic types Troubleshooting: Java runtime errors v

7 Contents 5 HAHTsite Server Object Model Introduction Built-in objects Getting references to the built-in objects From a Java project From a HAHTtalk Basic project The Application object Application object methods Application object variables Multiple processes and application-level variables Retrieving Application object properties Summary of Application object methods The Session object Session state Session timeout Event handling Creating a dynamic URL Creating a static URL Identification methods Summary of Session object methods The Request object Retrieving field values Retrieving cookie values Retrieving attachments Retrieving environment variables Summary of Request object methods The Response object Writing headers Setting cookies Writing the HTML output Summary of Response object methods Forms-Related Programming What s in this chapter Calling a subroutine from a form vi

8 Contents Writing the subroutine Associating the subroutine with a form Attaching a file to a form Adding a File Upload control to a page Working with a file attachment Custom Form Handler widgets Writing the form-handler function Creating the custom form-handler widget Form Fields Programming What s in this chapter Setting form-field properties Examples of setting form-field properties Setting and getting form-field properties FormField properties Button properties Checkbox properties Combo properties FileUpload properties ListElement and Listbox classes Radiobutton properties StaticText properties TextArea properties Textbox properties Calculating form-field values Calling user code from a button Code associated with a button versus code associated with a form Configuring a button to call user code Data-Agent Programming Data agents and command handlers Calling data-agent methods at runtime Setting a data agent s command Performing a data-agent action Getting and setting the values of a data agent s fields vii

9 Contents Getting a reference to a data agent s connection Dealing with recordsets Getting parameters to stored procedures Refreshing a data agent s data Sorting records Filtering records Handling errors Enabling tracing The structure of a command handler Modifying a command handler Where to add code to a command handler Examples of adding code to a command handler Changing the flow of control in a command handler Example of changing the flow of control Programming with the Connection Manager The DMConnectionManager class Opening a connection Opening a shared connection Opening a private connection Closing a connection Connections in HAHTtalk Basic projects Working with Client-side Scripts Introduction to client-side scripts Types of client-side scripts Choosing a scripting language Client-side scripts and the HTML editor Browsing the object model Configuring the Client Scripts view Writing in-line scripts Writing script functions HTML tags for client-side scripts viii

10 Contents About event handlers Scripting event handlers Browser compatibility issues The browser object model Strategies for handling browser incompatibilities About Dynamic HTML Moving objects using DTHML Why use Netscape Layers for positioning? JavaScript example for browser-independent DHTML Scripts with server-side expressions Using HtmlOut Routines or the HtmlOut Class Creating HTML at runtime The HAHTtalk Basic HtmlOut library Using the HAHTtalk Basic HtmlOut library HAHTtalk Basic example The HtmlOut Java class Java example Access Control What is access control? Granting privileges: the basics Controlling access to a page Controlling access to part of a page Displaying a custom error page Granting privileges to logged-in users Authenticating users with the Login widget Authenticating users with the Authentication interface Letting the Web server authenticate users Granting privileges on a user-name basis Using a Login widget and a database privilege repository Using a Login widget and a nondatabase privilege repository Using the Server Object Model ix

11 Contents Server Object Model methods Session class Privileges class Application class Authentication interface UserProfile interface Connecting to COM Objects Introduction Calling DLLs Declaring a DLL in HAHTtalk Basic Example DLL declarations Mapping HAHTtalk Basic types to DLL data types Using COM objects with HAHTtalk Basic The CreateObject function A COM Server example Background HAHTMem methods HAHTsite CORBA Capabilities Overview What is CORBA? What does HAHTsite/CORBA interoperation mean? Using CORBA with the HAHTsite IDE Handling CORBA projects Setting options for CORBA HAHTsite as a CORBA client Example: Building a HAHTsite CORBA client HAHTsite as a traditional CORBA server Example: Using CORBA to hold HAHTsite global state CORBA and the HAHTsite Server Object Model Using the HAHTsite Server Object Model in a HAHTsite CORBA server x

12 Contents Accessing the HAHTsite Server Object Model from a CORBA client Client/server communication Example: Using CORBA in a session initiated via HTTP Example: Initiating a HAHTsite application session with CORBA.327 Other Information Interoperability with other ORBS Using CORBA with HAHTtalk Basic VisiBroker installation and configuration VisiBroker SmartAgent and the CORBA Naming Service VisiBroker GateKeeper References Debugging Server-side Code Introduction Requirements for debugging A special case: debugging HAHTtalk Basic stand-alone programs.333 Starting a debugging session Debugging a code page Executing code in the debugger Single-stepping Procedure-stepping Using breakpoints The debug windows Debug output panel Variable window Watch window Call Stack window Threads window A HAHTsite 3.x WebApp Methods and Properties Introduction WebApp properties WebApp methods xi

13 Contents Pseudo-methods B HAHTsite 3.x Data Management Introduction DataSets and data agents Accessing and changing DataSet properties at runtime DataSet control functions Writing user-defined DataSet functions Accessing and changing form-control properties at runtime Connection-manager functions C Code Examples Calling a subroutine as a form action Modifying a command handler Writing a custom authentication class D ADO Primer What s in this appendix Connections Opening a connection Executing a command against a connection Closing a connection Recordsets Creating a recordset Iterating through the records in a recordset Finding a specific record in a recordset Reading a record Updating a record Inserting a record Deleting a record Closing a recordset E ADO Extensions What s in this appendix xii

14 Contents Extensions to the Java interface ADO tracing in Java projects Additional appendchunk methods The Variant data type Extensions to the HAHTtalk Basic interface ADO tracing in HAHTtalk Basic projects Functions for managing connections xiii

15 Contents xiv

16 About This Book The HAHTsite IDE Programming Guide explains how to extend your HAHTsite applications programmatically. Chapter 1, Introduction, gives you an overview of the programming capabilities available within HAHTsite. If you re developing a Java application, continue with Chapter 2, Working with Java Projects. If you re developing a HAHTtalk Basic application, look at the corresponding chapter, Chapter 3, Working with HAHTtalk Basic Projects. Then read Chapter 5, HAHTsite Server Object Model, which describes the programming model that underlies a HAHTsite application, including the Application, Session, Page, Request, and Response objects. This chapter, and all the chapters that follow, contain both HAHTtalk Basic and Java examples. However, the functionality is the same, regardless of which language you use. The table below lists each chapter in the HAHTsite IDE Programming Guide, along with its contents. Chapter/Appendix Chapter 1, Introduction Chapter 2, Working with Java Projects Chapter 3, Working with HAHTtalk Basic Projects Chapter 4, Calling Server-side Java from HAHTtalk Basic Chapter 5, HAHTsite Server Object Model Chapter 6, Forms-Related Programming Chapter 7, Form Fields Programming Contents A high-level introduction to the IDE s Server Object Model, data management model, and COM, CORBA, and client-scripting capabilities. Information for developers who are adding server-side code to a Java project. Information for developers who are adding server-side code to a HAHTtalk Basic project. How to call Java from a HAHTtalk Basic project. Explanation of the built-in objects in HAHTsite s Server Object Model. Customizing your application s form-handling capabilities. For HAHTtalk Basic projects, adding a custom form handler. Writing code that affects form fields and using a button to call user-written code. xv

17 About This Book Chapter/Appendix Chapter 8, Data-Agent Programming Chapter 9, Programming with the Connection Manager Chapter 10, Working with Client-side Scripts Chapter 11, Using HtmlOut Routines or the HtmlOut Class Chapter 12, Access Control Chapter 13, Connecting to COM Objects Chapter 14, HAHTsite CORBA Capabilities Chapter 15, Debugging Server-side Code Appendix A, HAHTsite 3.x WebApp Methods and Properties Appendix B, HAHTsite 3.x Data Management Appendix C, Code Examples Appendix D, ADO Primer Appendix E, ADO Extensions Contents Calling data-agent methods at runtime; customizing HAHTsite s command handlers. Opening and closing shared and private connections using the DMConnectionManager class. Adding JavaScript or VBScript to your application. Using HAHTsite functions/methods to create HTML at runtime. Controlling access to HAHTsite project items by assigning a set of required privileges to the items. Accessing DLLs and COM/DCOM objects from HAHTsite applications. Building HAHTsite applications that are CORBA clients or servers. Using HAHTsite s remote debugger to inspect code running on the Application Server. How WebApp properties and methods (from HAHTsite 3.x) relate to objects in the Server Object Model. How programming database applications differs between HAHTsite 3.x and HAHTsite 4.0. A set of sample functions/methods that supplement those in the text. How to perform basic operations using ADO connections and recordsets. The few ways in which HAHTsite s ADO implementation differs from the standard. xvi

18 Who is this book for? About This Book This book is written for use by HAHTsite programmers. It assumes that you: know how to use the HAHTsite IDE to create Web applications. have an understanding of how the HAHTsite IDE creates Web applications, how HAHTsite applications are structured, and how applications interact with the HAHTsite Application Server. know how to use either the Visual Basic or Java programming language. are familiar with HTML. Prerequisites In order to build a Java project that contains dynamic pages, or a HAHTtalk Basic project that calls server-side Java, you must have a Java compiler installed (not included with the HAHTsite software). See the ReadMe file for information on downloading a Java compiler. Conventions This book uses several conventions, which are described here. HAHTsite installation directory The directory into which you install the HAHTsite IDE is called the HAHTsite installation directory. This book uses the variable HAHTsiteInstallDir as a placeholder for the HAHTsite installation directory for example, C:\HAHTsite. When you see this variable, you should replace it with the name of the HAHTsite installation directory on your system. Continuation characters in sample code Some lines of sample code are too long to fit on one line. For HAHTtalk Basic code, this book uses the line-continuation character ( _ ) at the end of a line. For example: Function Create (instancehandle As Long, createtime As Integer, _ scopecount As Long) As Integer xvii

19 About This Book Screen images The HAHTsite IDE/IP runs on Windows 95, Windows 98, and Windows NT. Depending on which operating system you are using, the look of the screens might be slightly different from what you see in this book. However, the screens contents are the same. Other HAHTsite documentation The HAHTsite IDE includes this additional documentation: HAHTsite IDE and IP User s Guide HAHTsite IDE and IP Installation Guide HAHTsite Widget Programming Guide Getting Started The HAHTsite IDE/IP also includes an introduction to HAHTsite, lessons in using HAHTsite, and sample (HAHT_Intro) projects in Java and HAHTtalk Basic. Choose Getting Started from the Help menu. Online documentation In addition to the printed books, you can use the IDE/IP s online help system. As well as context-sensitive help for each of the dialogs, the online help system includes: Overview information about the IDE/IP. Step-by-step instructions on how to use the IDE/IP s features. Reference pages for the HAHTtalk Basic language, HAHTsite s Server Object Model, and the SQL Assistant. Information about using HAHTtalk Basic s Dialog Editor (used in building widgets). To open the help system, choose Contents and Index from the Help menu. xviii

20 About This Book HAHTsite OLE Interface Guide The HAHTsite IDE provides an OLE interface that you can access from your custom widgets. The OLE objects and methods are described in the HAHTsite OLE Interface Guide, which you can access from the IDE s Help menu. The HAHTsite OLE Interface Guide is an HTML document. The HAHTsite OLE Interface Guide is also installed as a HAHTsite project (in HAHTsiteInstallDir\sdk\oleapi). This enables you to add comments to the guide or to copy the guide s examples into the HAHTsite IDE and test them. Other HAHTsite products In addition to the IDE and the IP, the HAHTsite family of products includes the HAHTsite Application Server, which works with any Web server to execute HAHTsite applications. The Application Server runs on the Windows NT, HP/UX, Solaris, and AIX operating systems. It executes application logic, enables complete access to multiple data sources, maintains session information, and dynamically generates HTML pages. HAHT Software s commitment to you We want you to be completely satisfied with your HAHT Software products. If you have questions about HAHTsite, the HAHTsite IDE, the HAHTsite IP, or the HAHTsite Application Server, you can contact HAHT Software in the following ways: Telephone (919) Technical Support (Voice) (919) Technical Support (FAX) (888) Sales (Voice in the USA) (919) Office (Voice) (919) Office (FAX) xix

21 About This Book General Information Sales Support World Wide Web xx

22 Introduction 1 Overview...2 HAHTsite Server Object Model...3 The project package...3 The datamanager package...4 The form package...4 The access package...5 The corba package...5 Data-management API...5 ActiveX Data Objects classes...6 Relationship between ADO and SOM classes...6 Data management in HAHTtalk Basic projects...7 Client-side scripting...8 CORBA capabilities...9 Access to COM/DCOM objects...9 Remote debugging

23 Chapter 1: Introduction Overview Using HAHTsite s Integrated Development Environment (IDE), you can create many Web applications without writing any code. You describe your application s requirements using the IDE s graphical user interface, and HAHTsite s code generator creates the code for your application. Of course, code generators can t account for every contingency. Therefore, HAHTsite makes it easy for you to add your own code to this generated code as needed. In HAHTsite, you can add such code using either Java or HAHTtalk Basic (which is syntax compatible with Visual Basic). A Java virtual machine (either Microsoft or Sun) and a Basic virtual machine are embedded in the Application Server for the execution of code written in these languages. Being able to add Java or HAHTtalk Basic code to HAHTsite pages is useful in itself, but the real power of this language support lies in the fact that you can use these languages to call a tremendous amount of existing code. For instance, from either Java or HAHTtalk Basic, your Web application can call other code in DLLs, UNIX shared libraries, Java classes, or practically anything else that has a callable API. Of particular importance are the Java packages and Basic libraries supplied with HAHTsite. First, HAHTsite includes a set of Java packages that make up what is called its Server Object Model. The classes in these packages can be called from both Java and HAHTtalk Basic projects and enable you to: obtain information about the Application Server, about your application and individual user sessions, and about the data being passed back and forth between the Application Server and the Web server establish connections with relational and nonrelational data sources and to manage the ActiveX Data Objects (ADO) recordsets obtained via those connections control the form fields in your application s forms provide access control for the pages in your application make your application a CORBA server HAHTsite also includes a Java package and a Basic library that enable you to use the ActiveX Data Objects API for data management. 2

24 HAHTsite Server Object Model Chapter 1: Introduction The classes in the HAHTsite Server Object Model (SOM) are implemented in Java. At runtime, Java projects access SOM objects as real Java objects, and can subclass SOM classes and override SOM methods. You can also access the SOM from HAHTtalk Basic projects using HAHTtalk Basic syntax. However, some limitations apply; for example, SOM objects cannot be subclassed in a HAHTtalk Basic project. The classes in the SOM give you many capabilities, including the ability to examine requests sent from a Web browser, to manage data sources, and to protect information from unauthorized access. The principal packages in the SOM are: com.haht.project com.haht.project.datamanager com.haht.project.form com.haht.access com.haht.corba The project package The project package contains a number of built-in objects, which are available in every HAHTsite application. These objects are similar to the built-in objects in Microsoft s Active Server Pages. They let you control the data passed to and from a Web browser client and to get information about the application, the Web server, and the Application Server. When you run a HAHTsite application, each instance of a dynamic page is a Page object. You can also create dynamic pages programmatically, by implementing the HAHTPage interface in a Java project, or by implementing a Basic subroutine that generates HTML in a HAHTtalk Basic project. In addition to Page objects, each HAHTsite application contains these built-in objects: The Server object contains methods for storing variables that may be shared among multiple applications (as long as they are running in the same process on the Application Server). The Application object has information about the current application, as well as event handlers that are triggered when an application or session starts or ends. The Session object has information about the current session, which is defined as a browser client using the application. There is a separate Session object for each client. It also has two event handlers, called when a session is created and just before it s destroyed. 3

25 Chapter 1: Introduction The Request object s methods retrieve data the client browser sends to the Web server for example, form data or cookies. The Response object s methods generate HTML that the Web server sends to the browser. For further information about the project package, see Chapter 5, HAHTsite Server Object Model. The datamanager package The most important classes in the datamanager package are: DataAgent DMConnectionManager The DataAgent class represents an ADO recordset and enables you perform a variety of actions against that recordset. For example, you can use this class s methods to set the command that returns the recordset, to perform an action such as updating a record, or to get or set the value of a field in the recordset s current record. The DMConnectionManager class includes methods for opening ADO connections to relational or nonrelational data sources. These connections can be shared by two or more data agents within a session to lessen the amount of time your application spends establishing connections. Or they can be private so that you can perform transactions on the connection. The DataAgent and DMConnectionManager classes are discussed in detail in Chapter 8, Data-Agent Programming and Chapter 9, Programming with the Connection Manager, respectively. The form package The form package contains classes that represent the different types of form fields that you can place in a form, such as text boxes, combo boxes, and submit buttons. The methods of these classes enable you to perform tasks such as: setting a form field s value setting a text box s width setting the selected status of a list-box element Basically, all the form-field attributes that you can set in the IDE, you can also set at runtime. 4

26 Chapter 1: Introduction For further information about the form package, see Chapter 7, Form Fields Programming. The access package The access package includes classes that enable you to control access to HAHTsite pages. A Privileges class provides a container for a set of user-defined privileges, and each session contains a Privileges object. In addition, HAHTsite pages have associated with them a set of privileges. At runtime, the Application Server determines whether a session has access to a particular page in an application by comparing the privileges in the session s Privileges object with the page s privileges. The session can access a page only if all of that page s required privileges are contained in its Privileges object. This package also contains classes that enable you to: authenticate a user login retrieve a set of privileges from a repository by user name Chapter 12, Access Control, provides a complete explanation of how to use the classes in this package. The corba package The corba package enables you to create a HAHTsite application that plays the role of a CORBA server. Using the CORBA interface, clients can create sessions and invoke Java object methods. This CORBA interface enables applets running in a browser to communicate directly with the Application Server, bypassing the Web server. It also enables other CORBA applications in the corporate IT infrastructure to invoke services from the HAHTsite Application Server. A HAHTsite application can also function as a CORBA client. For further information about creating CORBA clients and servers, see Chapter 14, HAHTsite CORBA Capabilities. Data-management API In addition to the Server Object Model, HAHTsite includes both a Java package and a Basic library that provide a data-management API based on Microsoft s ActiveX Data Objects (ADO) 2.0. Java projects use the Java classes, and 5

27 Chapter 1: Introduction HAHTtalk Basic projects use the Basic classes. You can find documentation for both interfaces on Microsoft s Web site ( msdnlib.idc?theurl=/library/sdkdoc/dasdk/mdwe7i0f.htm). The ADO interface has the benefit of being well known and widely used by developers and, thus, is preferable to yet another proprietary data-access model. In addition, ADO is not tied to SQL, but allows access to both relational and nonrelational data sources. ActiveX Data Objects classes As mentioned earlier, HAHTsite s ADO interfaces are based on those of Microsoft ADO 2.0. If you re familiar with ADO programming, you know that the principal classes in the ADO object model are: Connection Command Recordset The Connection class represents a connection to a data source. An object of this type enables you to open and close a connection to a data source, to execute a command that returns a recordset from the data source, and to manage transactions on the connection. A Command object represents a command that queries a data source and returns a recordset. This command may be a SQL statement or some other textual command, the name of a database table, or the name of a stored procedure. A Recordset object contains the records returned over a connection following the execution of a query. Using a Recordset s methods, you can navigate the records in the recordset, add a new row to the recordset or delete an existing record, update a record, and so on. For information on how these ADO classes relate to the Server Object Model s DataAgent and DMConnectionManager classes, see Relationship between ADO and SOM classes on page 6. Relationship between ADO and SOM classes As you ve probably noticed, there s some overlap between the ADO object model and the Server Object Model s DMConnectionManager and DataAgent classes. You can use either or a combination of both for your data-management programming. Basically, the classes in the Server Object Model (SOM) provide a layer on top of the ADO classes that makes programming easier. The DMConnectionManager 6

28 Chapter 1: Introduction class enables you to create an ADO connection, and the DataAgent class not only represents an ADO recordset, but knows about the connection and the command used to retrieve that recordset. If you use the IDE to create connections to data sources and to create data agents, HAHTsite calls methods of the DMConnectionManager class and the DataAgent class in its generated code. So some of your data-management programming can be as simple as describing your requirements in the IDE. For situations where you need to perform tasks that aren t supported by the IDE, you can supplement the IDE s generated code with your own code that uses the DMConnectionManager and DataAgent classes, or you can use the ADO interface directly. Data management in HAHTtalk Basic projects In HAHTtalk Basic projects, you have two options when it comes to ADO programming. You can create Basic objects by making calls like this: Dim myconn As New ADODB.Connection myconn.open "..." Or you can create Java objects by using the classes defined in the package com.haht.ado, like this: Dim myconn As Object myconn = CreateJavaObject("com.haht.ado.Connection"...) myconn.open "..." Although both approaches are perfectly acceptable, the assumption is that Basic programmers will prefer to use Basic objects (the first approach). If you do use the Basic library for your ADO programming, make sure you understand that a Basic object and its Java counterpart are not type compatible. That is, a Basic recordset and a Java recordset do not have the same data type. Therefore, the following code will result in a type-mismatch error: Dim myrs As ADODB.Recordset... Set myrs = dataagent.getrecordset() The DataAgent class is a Java class, and the getrecordset method returns a Java object. A reference to this object cannot be assigned to myrs. One other note. The Java classes DMConnectionManager and DataAgent which are not part of the ADO object model, but define methods that return ADO objects do not have Basic counterparts. HAHTsite does include Basic 7

29 Chapter 1: Introduction functions that give you much of the functionality of the DMConnectionManager class. (These functions are discussed in Appendix E, ADO Extensions. ) However, to work with data agents, you must work with Java objects. Client-side scripting Most code in a HAHTsite application is executed by the Application Server; however, HAHTsite also provides support for writing client-side scripts to be executed in the user s browser. You can write these scripts in either JavaScript or VBScript. To help you develop scripts more easily, the HAHTsite IDE provides a Client Scripts view of each HTML page. In this view, you see a tree representation of the Document Object Model for the page. By navigating this tree, you can select specific objects that you want to associate event handlers with. For instance, you can navigate to a text box in a form and select the text box s onchange event. You can then use a script editor window to write a script that will be executed when this event occurs. The Document Object Model window also displays properties of the currently selected object and methods that may be applied to that object. If you drag one of these properties from the Document Object Model window to the editing window, HAHTsite constructs the appropriate reference, including correct capitalization and syntax. This drag-and-drop feature makes it easier to write client scripts. One other point. The task of writing client scripts and Dynamic HTML is complicated by variations in the Document Object Models in different browsers and different browser revisions. In general, the Document Object Model has become much more sophisticated and robust in later browser revisions, but pages that use the new browser features do not work in older browsers. The HAHTsite client-script editor enables you to view a particular Document Object Model. Thus, if you select the Internet Explorer 3.0 Document Object Model, HAHTsite will not display the new events and scriptable objects introduced in later versions of Internet Explorer and Netscape Navigator. This feature makes it easy to write scripts that work when the browser revision of your end users varies. For additional information about using JavaScript and VBScript in your applications, see Chapter 10, Working with Client-side Scripts. 8

30 CORBA capabilities Chapter 1: Introduction The software bundled with HAHTsite includes Inprise (formerly Visigenic) VisiBroker for Java, a suite of tools for building distributed-object applications. HAHTsite applications written using the HAHTsite Server Object Model can incorporate calls to the VisiBroker interfaces and thereby act as standard CORBA objects. Using CORBA s built-in capabilities, they can communicate with and become part of an enterprise built of distributed CORBA objects. Information from remote CORBA systems, such as mainframes, can be obtained by these CORBA-enhanced HAHTsite applications. This data can then be used in any manner within the HAHTsite application, providing a flexible, complete method to present enterprise information on the Web. In addition, there are several extensions to the HAHTsite Server Object Model that provide CORBA interfaces, allowing CORBA systems to operate directly on some HAHTsite server objects. This level of integration allows an external, non-hahtsite application to connect as a CORBA client to a CORBA-enabled HAHTsite application acting as a CORBA server. Such a client can initiate and control a HAHTsite session, making use of session capabilities such as automatic timeout. CORBA can also provide a Java applet running in a browser the ability to communicate with a HAHTsite application without the overhead of the HTTP protocol. For applets requiring substantial or very dynamic data from the server, this can be very beneficial. Access to COM/DCOM objects In a Microsoft environment, HAHTsite also provides full access to COM/DCOM objects. This access is native and does not depend on bridges from CORBA or other distributed object systems. From HAHTtalk Basic code, COM/DCOM servers are instantiated using the standard CreateObject call. Both in-process and out-of-process servers are supported. From Java code, COM/DCOM objects can be accessed via Java wrapper classes created using tools provided with the Microsoft SDK for Java. HAHTsite s ability to naturally and directly access COM/DCOM objects makes it easy to interface your HAHTsite application to other software products or custom code written for the Microsoft environment. For additional information, see Chapter 13, Connecting to COM Objects. 9

31 Chapter 1: Introduction Remote debugging HAHTsite supports remote debugging of both Java and HAHTtalk Basic code running in the Application Server (but not both in the same debug session). The Java and HAHTtalk Basic debuggers share the same IDE interface and have equivalent function except that Java code must be published with the debug option so that debug symbols are included. (HAHTtalk Basic code can be debugged without the debug option.) Debugging HAHTsite applications is discussed in detail in Chapter 15, Debugging Server-side Code. 10

32 Working with Java Projects 2 What s in this chapter...12 Adding server-side code to a Java project...12 In-line code...13 Invoking an expression or a method from a dialog box...15 Adding code in Server-side Code view...17 What s in a Java page?...18 Editing HahtApplication.java and HahtSession.java...25 Adding Java files to a project...26 Naming conventions for Java projects...30 Calling a dynamic page from Java...30 Event handling in a Java project...31 Editing and compiling Java code...37 Using the code editor...37 Compiling a Java application...38 Finding compile-time errors...39 Debugging a Java application...39 Working with application directories...39 Java options...41 Changing the Java file type...41 Overriding Java compiler options...42 Overriding options for JAR, CAB, and ZIP files

33 Chapter 2: Working with Java Projects What s in this chapter The first half of this chapter explains how to add server-side code that is, code that runs on the Application Server to a Java project. The second half of the chapter explains the mechanics of working with the code editor and compiling the code. Later chapters in this book give detailed explanations, with examples, of ways you can extend your HAHTsite application programmatically. For complete information about specific Java classes and methods, refer to the online help for the Server Object Model. In addition, if you are interested in further customizing your application with client-side scripts and applets, then be sure to look at Chapter 10, Working with Client-side Scripts, and the HAHTsite IDE and IP User s Guide, Chapter 20, Applets and Multimedia Objects. Note - The examples throughout this book assume the appropriate import statements and invoke Java methods without qualifying them with the full package name for example, they call Haht.getRequest() instead of com.haht.haht.getrequest(). HAHTsite s generated code uses the full qualification, to eliminate the possibility that a HAHTsite class might have the same name as another (non- HAHTsite) package you have imported. You may wish to do the same. Adding server-side code to a Java project With Java, you can easily extend the functionality of your HAHTsite Web applications beyond what you can do with HTML or CGI programs. In a HAHTsite Java project, you can use Java in these ways: 1 You can add in-line code to a page, intermixed with other HAHTsite elements such as text, pictures, and forms. The code can be a simple expression, a single line, or a complete block of code. See In-line code on page You can insert expressions and method calls in many of the dialogs in the IDE for example, a text box can be initialized with the value of an expression, and a form s action can be a call to a Java method. See Invoking an expression or a method from a dialog box on page

34 Chapter 2: Working with Java Projects 3 You can insert code in predefined places within the Java source for a page, using the HTML editor s Server-side Code view. See Adding code in Server-side Code view on page You can modify or add to the source code for the HahtApplication and HahtSession classes. See Editing HahtApplication.java and HahtSession.java on page You can create or import separate Java source files, with classes and methods that can be shared by all of the pages in an project and that can be reused in other projects. In addition, you can import Java class files as well as JAR, CAB, and ZIP files. See Adding Java files to a project on page 26. HAHTsite Server Object Model Much of this book describes classes and methods in HAHTsite s Server Object Model, which controls the structure of a HAHTsite Web application. With the Server Object Model, you can perform tasks such as reading data passed on the URL, writing HTML data, and controlling session timeout, as well as managing data source connections, setting form field values, and controlling access to dynamic pages. The Server Object Model is implemented in Java. However, it is equally accessible from HAHTtalk Basic projects, and the online help for the Server Object Model shows both the Java and HAHTtalk Basic syntax to call each method. External logic From your Java code, you also have access to Java classes outside the project and to capabilities such as CORBA, COM objects, and native methods. For more information, see Chapter 13, Connecting to COM Objects and Chapter 14, HAHTsite CORBA Capabilities. In-line code The ability to intermix Java code with other elements (such as text, pictures, widgets, and form elements) gives you a powerful tool for dynamically changing the content of Web pages. You can use this technique for many purposes for example: to control the flow of logic on the page 13

35 Chapter 2: Working with Java Projects to create internationalized pages that contain text in different languages from which a user can select to retrieve values passed on the URL from a calling page to override the value of a form field at runtime In-line code is typically used for short expressions and statements. To maintain the WYSIWYG look of your pages, you ll probably want to minimize the amount of code that you place directly onto a page. You can do this by creating classes and methods in a project s source pages and calling them from your Web pages. With this approach, you can also share classes and methods among the project s Web pages. In this example, a data agent (represented by the icon at the top of the page) populates a form with fields from a database. However, between the data agent and the form, note the code that disables the Next button if we ve reached end of file. Besides adding entire lines of code, you can also add expressions. An expression can include variables, constants, operators, and methods, as long as it resolves to a single value. Here are two examples: a * b / c arequest.geturlfield("txtcity") In the Java source, the IDE includes the expression in an out.print statement. 14

36 Chapter 2: Working with Java Projects To add a Java expression to an HTML page 1 On the page, click where you want the expression to appear. 2 Click the Server-side Expression button. 3 Type the expression. 4 By default, expressions are displayed in red in the editor, although you can change this setting using Tools > Options. To add a statement to an HTML page 1 On the page, click where you want the statement to appear. 2 Click the Server-side Statement button. 3 Type one or more statements. 4 By default, statements are displayed in blue in the HTML editor. To convert existing text to an expression or statement 1 Select the text you want to convert. 2 Click either the Server-side Expression button or the Server-side Statement button. Or choose Edit > Character, click the Script tab, and then select the type of expression or statement you want to create. To format the output of an expression or statement You can format the output of a Java expression or statement, just as you can format text that you type directly on the page. 1 Select the paragraph or characters you want to affect. 2 To modify the paragraph properties, choose Edit > Paragraph... or make a selection from the Paragraph Styles toolbar. 3 To modify the character properties, choose Edit > Character... or make a selection from the Character Styles toolbar. (If you modify the font color, the new color will be displayed in the browser, but not in the IDE.) Invoking an expression or a method from a dialog box The second way you can customize your project is through dialog boxes. From the HAHTsite IDE and IP User s Guide, you re probably aware of the many places that allow you to set project item properties using an expression rather than a field name or a constant, or that allow you to call a method instead of a dynamic page as a link or form action. 15

37 Chapter 2: Working with Java Projects Dialog box expressions To substitute an expression for a field name or constant, prefix the expression with ==. For example, in the properties for a link, you could define the query string to contain the entry point name of the current page: callingpage=/*==getname()*/ On the destination page, you could retrieve the information this way: arequest.geturlfield("callingpage") which would return packagename.class.method, like this: JavaExample.HsLinkStart.run Notice in the example the use of "/*" and "*/" bracketing the expression. You must use this construction when you want to use an expression in a name/value attribute pair, or when it appears in the middle of a script. However, if you simply want to set an attribute to the value of an expression, you can use ==expression. The expression must evaluate to a character string. 16

38 Chapter 2: Working with Java Projects Dialog box method calls In addition to using expressions, you can call user-defined methods from several property sheets in the IDE, such as the Form Properties dialog and the Link Properties dialog. For example: A Java method can generate the binary data to display a picture, an image map, or a multimedia object. It can be the destination for a dynamic link (the value of an HREF attribute tag). It can be the default action that takes place when the user submits a form, or the action tied to one of the form s buttons. Obviously, the content of your Java method will be determined primarily by what you want it to do, and the HAHTsite IDE and IP User s Guide explains any restrictions on calling a method or subroutine in the documentation for each set of properties. However, if the effect is to display a page, the class should implement the HAHTPage interface, including the run method: void run (Request arequest, Response aresponse) The run method and its arguments are described later in this chapter; see What s in a Java page? on page 18. Adding code in Server-side Code view The third way to customize your project is to add code directly to the serverside code for a page. When you include a dynamic page in a build or publish operation, the IDE generates a new Java source file for that page, extending the com.haht.project.page class. When you add in-line code to the page, it s inserted in the Java source, in the run method for that page. However, you may want to make other additions to the code for a page for example, you might want to add an import statement, add some initialization code to the run method, or call your own exception handler. The HTML editor s Server-side Code view lets you view the source code for a page, and lets you make additions, in predefined places, that will be preserved when the page is regenerated. (Note - you cannot change the generated source code; you can only add to it.) To view and add to the server-side code for a page 1 Open the page in the HTML editor. 2 Select View > Server-side Code, or click the Server-side Code view button. 17

39 Chapter 2: Working with Java Projects 3 Here are some points to note: The white areas mark places where you can insert code. The grayed-out areas mark generated source code, which is read-only. If you make changes in Server-side Code view, and then return to Normal view or HTML tags view, you will see your changes reflected. If the Server-side Code view button is disabled, be sure that you have saved the page. For more information on this process, see the note that follows. Behind the scenes: How does Server-side Code view work? To keep from overwriting your additions, the IDE must keep your code separate from the code it generates. When you add code in Server-side Code view, your code is translated into HTML tags and kept in the project s HTML file for this page. If you look at the page in HTML tags view, you will see sections like this: <SCRIPT language="hahtjava-statement"><!-- out.print(arequest.geturlfield("txtname"));--></script> When you build or publish the project, the code for the dynamic page is generated from the HTML file. What s in a Java page? For each dynamic page, the IDE generates a file (Hspagename.java) that defines a class Hspagename as a subclass of Page. The source code for each dynamic page has these contents: A package statement Import statements Class declaration and constructor A run method An exception handler A form handler Places to add classes and methods The following sections explain each of these topics, using as an example the Java source for a page that simply displays the current date. 18

40 Chapter 2: Working with Java Projects A package statement The package name is the name of the project. package ExamplProj; For more information about package names, see Naming conventions for Java projects on page 30. Import statements Each page source file imports several packages, including the HAHTsite packages for the Server Object Model and for data management. You can add your own import statements using the HTML editor s Server-side Code view. //////////////////////////////////////////////////////////////// // IMPORTS //////////////////////////////////////////////////////////////// import com.haht.*; import com.haht.project.*; import com.haht.io.*; import com.haht.project.form.*; import com.haht.project.datamanager.*; import com.haht.ado.abstract.*; import java.io.*; import java.util.*; // custom imports import com.haht.access.*; import java.text.*; Class declaration and constructor Each page has a constructor, called once per page per session to create the page object. If the page contains form fields, they are initialized here. You can also add custom code to the constructor. Notice the class declaration: the page name, which is simply ShowDate.html in the IDE, has become the class HsShowDate in the Java source for the page. For more information on dynamic page names, see Naming conventions for Java projects on page 30. You can add implements clauses if the class implements any additional interfaces. 19

41 Chapter 2: Working with Java Projects The constructor also gets references to both the Application object and the Session object references you can use anywhere in a dynamic page. These references are very useful in accessing application-level and session-level variables. public class HsShowDate extends com.haht.project.page // Specify implements declarations here. { /** * Default constructor for HsShowDate * **/ public HsShowDate () { hahtapplication = (HahtApplication) Haht.getApplication(); hahtsession = (HahtSession) Haht.getSession();... // Custom constructor code. } A run method Each page has a run method, with two arguments: the Request object and the Response object. The run method emits any header lines for example, Content-type: text/html Note that you can override the content-type header by another call to the Response object s setcontenttype method. See Adding content information to a header line on page 127. After emitting header lines, the run method then sets up the basic structure of the page, which would look like this in HTML: <HTML> <HEAD>...</HEAD> <BODY>...</BODY> </HTML> 20

42 Chapter 2: Working with Java Projects When you add in-line code to a page, it s normally added here, between the <BODY> and </BODY> tags. (Some code such as setting a cookie must be output with the HTTP headers. HAHTsite automatically handles this code correctly. See Writing headers on page 126.) Notice the marked sections where you can add local variables, initialization code, and custom HTTP response headers (two places). You can also edit any in-line code. In this example, the page contains two lines of in-line code, to set the date. /** * Runs the page, producing HTML. * arequest - HTTP request for this page aresponse - HTTP response for this page * **/ public void run(com.haht.project.request arequest, com.haht.project.response aresponse) { HtmlWriter out; // user-defined run() local variables try { // Initialize variables. out = aresponse.getwriter(); // Custom initialization code executes before HTML // tags are generated. // Output HTTP response headers. // Custom HTTP Response Headers. aresponse.setcontenttype("text/html"); out.print("\r\n"); // More Custom HTTP Response Headers. 21

43 Chapter 2: Working with Java Projects // Generate HTML. out.print("<html>\r\n"); out.print("<head>\r\n"); out.print(" <META name=\"generator\" content=\"hahtsite 4.0\">\r\n"); out.print(" <TITLE>ShowDate</TITLE>\r\n"); out.print("</head>\r\n"); out.print("<body>\r\n"); out.print(" <P>"); Date d = new Date(); out.print(d); out.print("</p>\r\n"); out.print(" <P> </P>\r\n"); out.print("</body>\r\n"); out.print("</html>"); // All HTML has been generated. Put cleanup code here. } // try catch (java.lang.throwable t) { handleexception(t, "HsShowDate", arequest, aresponse); } // catch } // End of run method References to the Request and Response objects The run method, seen in the example above, has two arguments: the Request object (arequest), whose methods get information from the Web browser for example, methods to read data passed in a form field or on the URL. the Response object (aresponse), whose methods send information to the Web server for example, HTML output and cookies. The Request and Response objects are built in to your HAHTsite application, along with the Application and Session objects. Both these object references (arequest and aresponse) will be useful in your in-line code. For example, to read a value passed in a form or on the URL, you would call arequest.geturlfield. 22

44 Chapter 2: Working with Java Projects Note - For information about using the variables and methods of the Application and Session objects, see Calling a dynamic page from Java on page 30. For general information on the HAHTsite Server Object Model s built-in objects, see Built-in objects on page 90. A reference for writing HTML output The run method also gets a reference to the default HtmlWriter. To write HTML output programmatically, you can use statements like this: out.print(d); Of course, you can also intermix text and in-line code on a page. In the Java source, the text turns into out.print statements. An exception handler The run method of every dynamic page calls a general-purpose exception handler, handleexception, to catch runtime errors and print an error message similar to this. You can override this method or add other exception handlers to your code. A form handler The Java source for each dynamic page contains a form handler that adapts to the contents of the page. At runtime, when a user submits a form, the form handler determines which button was clicked and calls the appropriate command handler. Because this page doesn t contain a form, it has no command handlers. If it did, you would see additional places in which you can customize the command handlers by writing your own event-handling code. For more information, see Chapter 8, Data-Agent Programming. 23

45 Chapter 2: Working with Java Projects /** * Entry point that is called via URL when a form is * submitted from this page. * arequest - HTTP request for this page aresponse - HTTP response for this page * **/ public void mapformtocmd (com.haht.project.request arequest, com.haht.project.response aresponse) { boolean bcmdhandlercalled = false; if (! bcmdhandlercalled) { geterrors().add("received form command did not invoke a command-handler", "form-handler"); run (arequest, aresponse); } } Places to add classes and methods In Server-side Code view, you will see a number of marked sections where you can add classes, methods, and variables: public, protected, and private methods static initializer code nested classes public, protected, and private member variables // user-defined public methods // protected methods // user-defined protected methods 24

46 Chapter 2: Working with Java Projects // private methods // user-defined private methods // static initializer code static { // Initialization code for user-defined static variables. } // nested classes // user-defined nested classes // public member variables // user-defined public variables // protected member variables protected HahtApplication hahtapplication; protected HahtSession hahtsession; // user-defined protected variables // private member variables // user-defined private variables Editing HahtApplication.java and HahtSession.java In addition to one or more Page subclasses, your HAHTsite application includes a HahtApplication class and a HahtSession class, which you can see in your project window. 25

47 Chapter 2: Working with Java Projects You can open these files in the code editor and add variables and methods to these classes. You can use HahtApplication to cache variables that may be shared by multiple sessions. Use HahtSession to store variables that apply across page boundaries. A session recordset is a particularly powerful use of the HahtSession object. You can update a recordset on one page and use it to populate a form on another, without reaccessing the database. Both HahtApplication and HahtSession contain event handlers that you can edit; see Event handling in a Java project on page 31. For more information about these files, see Built-in objects on page 90. Note - Do not call Server Object Model methods from the constructors in HahtApplication and HahtSession. The Server Object Model must be initialized first. Instead, edit the onstart and onend methods. Adding Java files to a project The final way to add server-side Java to your project is by creating a Java source file or by importing a Java source file, class file, or JAR, CAB, or ZIP file, to be used by any of a project s dynamic pages. In a Java project, all Java files should be stored in the Packages folder. You can use the same package name as the page files (that is, the project name), or you can create additional packages and store the Java files in subfolders under Packages. 26

48 Chapter 2: Working with Java Projects Note - If you (1) omit the package statement in a Java source page and (2) reference one of its classes from an HTML page, some compilers will generate a class not found compiler error. To avoid this problem, put all your source code in packages and use the appropriate package import statements. To add a new Java source page 1 Choose File > New > Java Source... The New Java Source dialog appears. 2 Select the type of Java code you want to create: Type Applet Common Server-side Java Servlet Description Source for a Java applet Java source that may be used in both server-side code and applets Source for Java code that will run on the server Source for a Java servlet a Web server plug-in that allows dynamic content to be created using Java on the server side 3 Click OK to open the Java source file. 27

49 Chapter 2: Working with Java Projects To import a Java source, class, JAR, CAB, or ZIP file In addition to creating new source files in your project, you can import existing Java files, including: Type Description Extension Java source Java source code.java Class file Compiled Java code.class JAR file Java CAB file Java ZIP file Java archive file, which can contain multiple files (class files, images, etc.) Collection of Java class files in Microsoft s Java Cabinet format Collection of Java class files in ZIP format, typically uncompressed.jar.cab.zip 1 In the project window, select the folder in which you want to store the imported file. For server-side Java, files must be stored in the Packages folder. (Applets, on the other hand, are stored in the Web folder.) 2 Choose File > Import File... The Import Files dialog appears. 28

50 Chapter 2: Working with Java Projects 3 Type or browse for one or more filenames. 4 Choose Copy Files or Create Shortcuts. If you want to maintain one central version of a file but use it in several projects, you may want to create a shortcut. 5 In the combo box marked Import Java files as, select the type of Java code you are importing server-side, applet, servlet, or common. 6 Click OK to complete the import. For more information about imported files, including information about source control, consult the HAHTsite IDE and IP User s Guide, Chapter 3, Managing Projects. To save a source code page 1 Select File > Save. The Save Code Page As dialog appears. 2 Type in a page name, or accept the default name. The suffix must be.java. 3 To save the code page inside the project, browse within the Project Items window for the folder name you want. 4 If the project is in source control, you will see an additional checkbox: Add to source control. Check this box to add this file to the source control system. 5 Click OK to save your changes. To save a source code page outside the project To be called from within the project, a source code page must be saved inside the project. However, you can also save it to a file outside the project. 1 Select File > Save. The Save Code Page As dialog appears. 2 Click the Save to File... button. The Save As dialog appears. 3 Browse for a folder location and enter a filename. 4 Click OK to save your changes. 29

51 Chapter 2: Working with Java Projects Naming conventions for Java projects HAHTsite uses certain naming conventions for Java projects. In a HAHTsite Java project, project names become package names. Project names must be unique within a site. Any valid filename can be used as a project name, with one exception: Java keywords cannot be used as project names (you ll get an error when you create the project). When the IDE generates the package name, it turns any nonalphanumeric characters (including spaces) to underscores (_). Naming conventions for dynamic pages When the IDE generates the Java code for a dynamic page, the page becomes a Java class. All the dynamic pages in a project are placed in the same package, regardless of the directory structure you may have set up within the project. This means that page names must be unique to the entire project, since class names must be unique within a package. (Note: you can have source pages in different packages; this rule applies only to dynamic pages.) The IDE prepends Hs" to the page name, so that a page named Welcome would become the class HsWelcome. Any valid filename can be used as a page name. When it generates the class name, the IDE converts non-alphanumeric characters (anything other than A-Z, a-z, and 0-9) to underscores. For example, Page 1.html, Page_1.html, and Page$1.html would all resolve to the class HsPage_1. Calling a dynamic page from Java When a user browses a dynamic page for the first time, HAHTsite instantiates the page object and invokes its run method. If the user returns to the same page, rather than instantiating the page again, HAHTsite uses a reference to that page. You can do the same thing in your application, when you call a dynamic page programmatically. In a Java application, you instantiate a dynamic page by calling the Session object s returnhahtpageobject method and passing it the 30

52 Chapter 2: Working with Java Projects fully-qualified page name (that is, packagename.classname). If the page hasn t already been instantiated, returnhahtpageobject instantiates the page object and returns a reference to it; otherwise, it simply returns the object reference. (If for some reason, you want a new instance of the page, then you can use new rather than returnhahtpageobject.) You call a dynamic page by invoking its run method. This code instantiates a dynamic page called MyNewPage, in a project called ExampleProj: HAHTPage MyNewPage = hahtsession.returnhahtpageobject ("ExampleProj.HsMyNewPage"); To call its run method, you would use this code: MyNewPage.run(aRequest, aresponse); Event handling in a Java project If you look at the code for HahtApplication.java and HahtSession.java, you ll see several methods that are triggered when an application or a session starts or ends. In a Java project, you can add your own code to these six methods: Application method onstart onend onsessionstart onsessionend Description Called right after a new application is created, but before any pages are run. Called just before an application is destroyed. Called when a new session is created, but before any pages are run. (Called for each session. This method is called before the Session object s onstart method.) Called just before a session is destroyed. (Called for each session. This method is called after the Session object s onend method.) 31

53 Chapter 2: Working with Java Projects Session method onstart onend Description Called when a new session is created, but before any pages are run. (Called once, for the current session.) Called just before a session is destroyed. (Called once, for the current session.) Note: onend is called even if onstart fails. When are these methods useful? In the Session object s onstart method, you could populate a session recordset for use by subsequent pages in the session for example, you might want to read in the values of a database table (a catalog, say) that s used by several different pages. In the onend method, you might want to save the session state, so that you can restore it later if the user returns to the application. If onstart fails, the Application Server calls onend and terminates the application or session without running any pages. There are two ways for onstart to fail: You can throw a runtime exception, such as this: throw new RuntimeException("Failed in onstart"); In this case, the Application Server calls onend, generates a runtime error message, and terminates the session. You can edit the onstart method to produce a custom diagnostic page. Generally, after producing a diagnostic page, you want to prevent any further running of the session and any further error output from the Application Server, so you should also call the Session object s abandon method, which calls onend and terminates the session. Java Response aresponse = Haht.getResponse(); aresponse.setcontenttype("text/html"); aresponse.endheaders(); aresponse.write("exiting the session <br>"); aresponse.write("failed in onstart <br>"); // Abandon the session Haht.getSession().abandon(); The onend methods are passed an ApplicationEvent or SessionEvent object. By calling this object s getreason method, you can determine the reason for the event. For a session ending, the available reasons are: 32

54 Chapter 2: Working with Java Projects SessionEvent.SESSION_TIMEOUT - session timed out normally SessionEvent.SESSION_STOP_END session was stopped by a call to the abandon method SessionEvent.SESSION_TERMINATED session was terminated by an administrator SessionEvent.SESSION_START_ERROR the onstart method threw an exception The example that follows uses the Application object s onsessionstart and onsessionend methods to update a variable that tracks active sessions. Example: onsessionstart, onsessionend Suppose you want to keep track of the number of currently-active sessions in an application. At any point in the application, you want to be able to print out this information. You might begin by creating a static variable, called nactivesessions, in the HahtApplication class. Notice two particular methods in this class onsessionstart, which is called each time a session is started, and onsessionend, which is called when a session times out. You can add code to those methods to increment and decrement nactivesessions appropriately. You ll also want to add a method to return the value of nactivesessions. Here is the code in the HahtApplication class (ellipses mark boilerplate code that has been omitted). 33

55 Chapter 2: Working with Java Projects Java /** * ExamplProj.HahtApplication.java **/ //////////////////////////////////////////////////////////////// // PACKAGE //////////////////////////////////////////////////////////////// package ExamplProj; /////////////////////////////////////////////////////////// // IMPORTS /////////////////////////////////////////////////////////// import com.haht.*; import com.haht.project.*; /** * HahtApplication class * * Represents a HAHTsite web application. * Put customizations for an application in this class. * * This class is derived from GeneratedApplication. * GeneratedApplication is built by the HAHTsite IDE * according to your project configuration. * * ExamplProj.GeneratedApplication com.haht.project.application * **/ public class HahtApplication extends ExamplProj.GeneratedApplication { /** * Default constructor for HahtApplication **/ public HahtApplication() { } 34

56 Chapter 2: Working with Java Projects Java /** * Called when a new session is being created. * anevent Describes details about the event. * **/ public void onsessionstart (com.haht.project.sessionevent anevent) { // As each session starts, increment total count nactivesessions++; } /** * Called right before a session is destroyed. * anevent Describes details about the event. * **/ public void onsessionend (com.haht.project.sessionevent anevent) { // As each session ends, decrement total count nactivesessions--; } /** * Called when a new application is being created. * anevent Describes details about the event. * **/ public void onstart(com.haht.project.applicationevent anevent) { } 35

57 Chapter 2: Working with Java Projects Java } /** * Called right before a application is destroyed. * anevent Describes details about the event. * **/ public void onend(com.haht.project.applicationevent anevent) { } /* * Keep track of number of currently-active sessions */ private static int nactivesessions=0; public int getactivesessioncount() { return nactivesessions; } Now you re ready to add some in-line code to a dynamic page. The line shown below contains text and an expression calling the method you added to return the number of active sessions. It also prints the current date and time. At [insert DateTime widget] there are hahtapplication.getactivesessioncount() active sessions. The generated code for a dynamic page automatically defines hahtapplication and hahtsession to refer to the Application and Session objects, respectively, and casts them appropriately. You can use both these references anywhere in a dynamic page. For more information, see Application and Session references in a dynamic page on page 92. (By the way, if you try this example, at runtime you may notice a lag between the time a user leaves the application and the time the onsessionend method is called. This is due to the session timeout; see Session timeout on page 108.) 36

58 Editing and compiling Java code Chapter 2: Working with Java Projects This section explains the mechanics of writing Java code in the IDE: Using the code editor Compiling a Java application Working with application directories Using the code editor When you open a source file into the IDE s Code window, the Select Object/Select Event combo boxes contain the names of the file s objects and methods. To jump to an object or method in the source code Select its name from the combo box. To move to the next or previous method on the page Click the up or down arrow. To jump to a specific line of code 1 Click inside the source file (open in the code editor) and choose Edit > Go to... The Go to line dialog appears. 37

59 Chapter 2: Working with Java Projects 2 In the Line number field, enter the line number from the compiler s error message. 3 Click OK. The cursor s line number is displayed in the lower right-hand corner of the IDE s window. To hide (or make visible) the code on a page Select View > Code as Icon. All the code on the page is toggled between viewing as icon or viewing as text. To view more than one file in a split window Select Window > Tile. The files that are open in the workspace are tiled (to a maximum of four files), so that you can view one file while you re editing another. Compiling a Java application When you publish a Java project, the IDE converts each dynamic page to a Java code (.java) file. Then it compiles all Java code, including source pages, generating class files that it publishes to the project s application root directory (server-side code) or static root directory (applets). You can also compile a single file for example, to check for syntax errors: With the file open in the code editor, select Java > Build. (This option is not available for dynamic pages.) Note - If a file is not compiled as you expected, be sure that you have identified it correctly to the project as server-side, applet, servlet, or common. To check (and optionally change) this identification, see Changing the Java file type on page 41. A Java application is compiled using the options set in the IDE, using the Tools > Options > Java Options dialog. For each type of Java source file server-side, applet, servlet, or common the IDE has a profile, specifying the path to the default compiler as well as the classpath and output directory. When you install the IDE, these profiles are created with default values, but you can 38

60 Chapter 2: Working with Java Projects modify the profiles, and you can override the defaults for a particular project and/or for any Java source file in the project. For more information, see Overriding Java compiler options on page 42. Again by default, server-side and common JAR files are automatically added to the compile-time and runtime classpath, but applet and servlet JARs are not. You can override this default behavior for any JAR file in your project. (This information applies to CAB and ZIP files as well.) For more information, see Overriding options for JAR, CAB, and ZIP files on page 43. Finding compile-time errors If the Java compiler finds a syntax error in your Java code, it sends an error message to the project s Build/Publish window. In many cases, you can see what the problem is by looking at the error message. (Recall that the Java compiler options set the amount of parsing for error messages. Choose Tools > Options > Java, and edit your server-side Java compiler profile.) To navigate the compiler s error messages You can scroll through the messages in the Build/Publish window, double-clicking on any message with a + to expand it. If you doubleclick the error message, the IDE opens the file if necessary and displays the relevant line. Or you can choose Edit > Find Error > [First, Next] to go to that particular error in the Build/Publish window. The IDE opens the file if necessary and displays the relevant line. Debugging a Java application HAHTsite includes a source-level debugger that lets you debug HAHTsite Java applications, even remotely. You must compile the Java application with the debug option set: from the Build Type combo box in the IDE s toolbar, choose Debug. (This is the default.) For more information about running the debugger, see Chapter 15, Debugging Server-side Code. Working with application directories HAHTsite Java applications use three special directories: the static root directory, userroot, and approot. You set these directory locations when you install the IDE and Application Server or when you modify their configurations. These root directories are shared by all applications within a 39

61 Chapter 2: Working with Java Projects particular server group, but you can differentiate between them by using the subdirectory macros %project% and/or %username%. (Otherwise, files from one project could overwrite files with the same name from another project.) Static root directory The static root directory is the directory where the Web server gets the application s static pages (.htm and.html files), graphics files, and any other files not run by the HAHTsite Application Server. Note - Secure static pages are stored in the project s approot directory. To retrieve the directory pathname (in either NT or UNIX format, depending on the operating system), you could use code like this: String mystaticroot = hahtapplication.getstaticroot(); To retrieve the URL for the static-page directory, you could use code like this: String mystaticurl = hahtsession.getstaticurl(); Userroot and approot The userroot and approot directories are used by the HAHTsite Application Server. userroot is the application s initial working directory. At runtime, a HAHTsite application has a current, or initial working directory on the server. In your Java code, if you read or write a file by specifying just the file s name, the application looks for the file in the application s initial working directory. To retrieve this pathname, you could use code like this: String myuserroot = hahtapplication.getuserroot(); approot, the application root directory, is the directory in which a HAHTsite Application Server finds an application s executable files (.class,.jar,.zip, and.cab files), as well as its secure static pages. To check where the project s executable files were published, relative to the approot directory, you could use code like this: String myappdir = hahtapplication.getdirname(); If the method returns \ or /, the files were published directly to the application root directory. Otherwise, the method returns the path to the subdirectory. (Note that this method does not return the full path to the application root directory.) You may also notice a javaroot directory, which holds Java class files for a HAHTtalk project, but which is not used by Java projects. 40

62 Java options Chapter 2: Working with Java Projects In the IDE, the Tools > Options > Java Options dialog defines the default compiler and compile-time options, such as classpath and output directory, that apply to your Java files. However, for any project, and for any Java source file within a project, you can override both the default compiler and the compile-time options. And for any JAR, CAB, and ZIP file, you can specify whether it should be included in the compile-time and/or runtime classpath. You can also view and change the Java file type. Changing the Java file type The General properties of a Java source file list its name and Java file type: server-side, applet, servlet, or common. If you create or import a file but specify the wrong type, you can change the type on this property sheet. 1 In the project window, select the filename and choose Edit > Properties. 2 From the drop-down list in the Type field, select a new type. For more information on the Java file types, see Adding Java files to a project on page

63 Chapter 2: Working with Java Projects Overriding Java compiler options If you override Java options at the project level, the new options will apply throughout your project. However, you can also specify overrides at the file level. 1 To override Java options at the project level: In the project window, select the project name and choose Edit > Properties... Click the Java Compiler tab. You will see a list of Java file types, and the default compiler for each. To modify the default for a particular file type, select it and click Modify... 2 To override source-file options: In the project window, select the filename and choose Edit > Properties. Click the Java Compiler tab. 3 The Java Compiler dialog appears. 42

64 Chapter 2: Working with Java Projects 4 To override the default compiler, uncheck the Use Default Compiler box, and select a compiler from the drop-down list. The compiler must have been previously defined in the Tools > Options > Java Options dialog. 5 To override the compiler settings, check the Override Compiler Settings box. The boxes below will no longer be grayed out, and you can define a different classpath, output directory, or other compiler option. For details on setting these options, see the Java Options section of the HAHTsite IDE and IP User s Guide, Chapter 2, Using the IDE/IP s Windows and Toolbars. Overriding options for JAR, CAB, and ZIP files JAR, CAB, and ZIP files are treated differently in a HAHTsite project, depending on whether you identify them as server-side, applet, servlet, or common files. (For brevity s sake, this section refers only to JARs, but the information applies equally to JAR, CAB, and ZIP files.) Server-side and common JARs are automatically added to the project via the %(ProjectJars) macro in the compile-time classpath. When you publish your project, the Application Server also automatically adds the JAR file to the runtime classpath for the application. 43

65 Chapter 2: Working with Java Projects By default, applet and servlet JARs are not automatically added to either the compile-time classpath or the application s runtime classpath. You can change the compile-time or runtime defaults for a specific JAR file, using the Jar Properties dialog in the project window. 1 In the project window, click on a JAR file to select it. The Jar Properties dialog appears. 2 Respond to the prompts: Item Type Add to compiler class path Add to project s runtime class path in application server Description To change the type of JAR file (server-side, applet, servlet, or common), make another selection from the drop-down box. Check if you want this JAR added to the compiletime class path. Check if you want this JAR added to the runtime classpath. 44

66 Working with HAHTtalk Basic Projects 3 What s in this chapter...46 Adding server-side code to a HAHTtalk Basic project...46 In-line code...48 Invoking an expression or a subroutine from a dialog box...50 Adding code in Server-side Code view...52 What s in a HAHTtalk Basic page?...53 Adding HAHTtalk Basic files to a project...60 Naming conventions for HAHTtalk Basic projects...62 Include files and Globals.hbs...63 Project and external includes...63 Declaring public variables with Globals.hbs...64 Precompiler directives...64 Calling dynamic pages from HAHTtalk Basic...65 Event handling in a HAHTtalk Basic project...66 Editing and compiling HAHTtalk Basic code...67 Using the code editor...67 Compiling a HAHTtalk Basic application...69 Finding compile-time errors...69 Debugging a HAHTtalk Basic application...70 Working with application directories...70 Comparing HAHTtalk Basic and Visual Basic

67 Chapter 3: Working with HAHTtalk Basic Projects What s in this chapter The first half of this chapter explains how to add server-side code that is, code that runs on the Application Server to a HAHTtalk Basic project. The second half of the chapter explains the mechanics of working with the code editor and compiling the code. Later chapters in this book give detailed explanations, with examples, of ways you can extend your HAHTsite application programmatically. For complete information about specific classes and methods, refer to the HAHTsite Server Object Model and the HAHTtalk Reference in the online help. In addition, if you are interested in further customizing your application with client-side scripts and applets, then be sure to look at these chapters: In this book: Chapter 10, Working with Client-side Scripts In the HAHTsite IDE and IP User s Guide: Chapter 20, Applets and Multimedia Objects Adding server-side code to a HAHTtalk Basic project With HAHTtalk Basic, you can easily extend the functionality of your HAHTsite Web applications beyond what you can do with HTML or CGI programs. In a HAHTsite HAHTtalk Basic project, you can use HAHTtalk Basic in these ways: 1 You can add in-line code to a page, intermixed with other HAHTsite elements such as text, pictures, and forms. The code can be a simple expression, a single line, or a complete block of code. See In-line code on page You can insert expressions and method calls in many of the dialogs in the IDE for example, a text box can be initialized with the value of an expression, and a form s action can be a call to a HAHTtalk Basic subroutine. See Invoking an expression or a subroutine from a dialog box on page You can insert code in predefined places within the source code for a page, using the HTML editor s Server-side Code view. See Adding code in Server-side Code view on page

68 Chapter 3: Working with HAHTtalk Basic Projects 4 You can create separate source files, with functions and subroutines that can be shared by all of the pages in an project and that can be reused in other projects. In addition to creating or importing HAHTtalk Basic source files, you can import compiled HAHTtalk Basic files as well. See Adding HAHTtalk Basic files to a project on page 60. HAHTsite Server Object Model Much of this book describes classes and methods in HAHTsite s Server Object Model, which controls the structure of a HAHTsite Web application. With the Server Object Model, you can perform tasks such as reading data passed on the URL, writing HTML data, and controlling session timeout, as well as managing data source connections, setting form field values, and controlling access to dynamic pages. The Server Object Model is implemented in Java. However, it is equally accessible from HAHTtalk Basic projects, and the online help for the Server Object Model shows both the Java and HAHTtalk Basic syntax to call each method. A few methods are not meaningful in a HAHTtalk Basic project, and for those methods the syntax is shown as n.a. For more information about Java, you may wish to look at Chapter 4, Calling Server-side Java from HAHTtalk Basic. You may already be familiar with calling CreateObject or CreateJavaObject, to access COM objects or Java objects from Basic. However, HAHTsite s Server Object Model has a set of builtin objects. You do not need to instantiate them in order to call their methods. External logic From your HAHTtalk Basic code you also have access to capabilities such as CORBA, COM/DCOM, and native methods. For more information, see the table below. External logic Server-side Java CORBA COM/DCOM ActiveX object calls Database Stored Procedure Calls Where described Chapter 4, Calling Server-side Java from HAHTtalk Basic Chapter 14, HAHTsite CORBA Capabilities Chapter 13, Connecting to COM Objects Online help Chapter 8, Data-Agent Programming 47

69 Chapter 3: Working with HAHTtalk Basic Projects External logic Windows DDE calls Sending SMTP messages FTP operations to a remote server Using the shell command to create an external process Socket operations Where described Online help Online help Online help Online help Online help UNIX API system calls Windows API systems calls Online help In-line code The ability to intermix HAHTtalk Basic code with other elements (such as text, pictures, Widgets, and form elements) gives you a powerful tool for dynamically changing the content of Web pages. You can use this technique for many purposes for example: to control the flow of logic on the page to create internationalized pages that contain text in different languages from which a user can select to modify values read in from a database or from the URL To maintain the WYSIWYG look of your pages, you ll probably want to minimize the amount of code that you place directly onto a page. You can do this by creating functions and subroutines in a project s source pages and calling them from your Web pages. With this approach, you can also share functions and subroutines among the project s Web pages. This example shows a form whose first-name and last-name text box values are being overridden by global variables from in-line code at the top of the page. 48

70 Chapter 3: Working with HAHTtalk Basic Projects Besides adding entire lines of code, you can also add expressions. An expression can include variables, constants, operators, and functions, as long as it resolves to a single value. Here are two examples: Date$ Haht.getRequest().getURLField("txtCity") In the HAHTtalk Basic source, the IDE includes the expression in a Print statement. To add a HAHTtalk Basic expression to an HTML page 1 On the page, click where you want the expression to appear. 2 Click the Server-side Expression button. 3 Type the expression. 4 By default, expressions are displayed in red in the HTML editor. However, you can override this setting in Tools > Options > Editor. To add a statement to an HTML page 1 On the page, click where you want the statement to appear. 2 Click the Server-side Statement button. 3 Type one or more statements. 4 By default, statements are displayed in blue in the HTML editor. 49

71 Chapter 3: Working with HAHTtalk Basic Projects To convert existing text to an expression or statement 1 Select the text you want to convert. 2 Click either the Server-side Expression button or the Server-side Statement button. To format the output of an expression or statement You can format the output of a HAHTtalk Basic expression or statement, just as you can format text that you type directly on the page. 1 Select the paragraph or characters you want to affect. 2 To modify the paragraph properties, choose Edit > Paragraph... or make a selection from the Paragraph Styles toolbar. 3 To modify the character properties, choose Edit > Character... or make a selection from the Character Styles toolbar. (If you modify the font color, the new color will be displayed in the browser, but not in the IDE.) Invoking an expression or a subroutine from a dialog box The second way you can customize your project is by invoking expressions or subroutines inside a dialog box for example, to set link properties or form properties. From the HAHTsite IDE and IP User s Guide, you re probably aware of the many places in property-sheet dialog boxes that allow you to use an expression rather than a field name or a constant, or that allow you to call a subroutine instead of a dynamic page as a link or form action. Dialog box expressions To substitute an expression for a field name or constant, prefix the expression with "==". For example, in the link properties, you could set the query string to contain the value of the (String) variable "CityCode": Code=/*==CityCode*/ 50

72 Chapter 3: Working with HAHTtalk Basic Projects On the destination page, you could retrieve the information this way: Print arequest.geturlfield("code") Notice in the example the use of "/*" and "*/" bracketing the expression. You must use this construction when you want to use an expression in a name/value attribute pair, or when it appears in the middle of a script. However, if you simply want to set an attribute to the value of an expression, you can use ==expression. The expression must evaluate to a character string. Dialog box subroutine calls In addition to using expressions, you can call user-defined subroutines (not functions) from several dialogs in the IDE, such as the Form Properties dialog and the Link Properties dialog. For example: A subroutine can generate the binary data to display a picture, an image map, or a multimedia object. It can be the destination for a dynamic link (the value of an HREF attribute tag). 51

73 Chapter 3: Working with HAHTtalk Basic Projects It can be the default action that takes place when the user submits a form, or the action tied to one of the form s buttons. Obviously, the content of your subroutine will be determined primarily by what you want it to do. However, if its effect is to display a page, it should emit the <HEAD>...</HEAD> and <BODY> and </BODY> HTML tags. For an annotated view of a typical page, see What s in a HAHTtalk Basic page? on page 53. Adding code in Server-side Code view The third way to customize your project is to add directly to the server-side code for a page. When you build or publish your project, the IDE generates a pagename.hbs file for every dynamic page. (These generated files are stored in your project s sites directory and don t appear in the project window.) If you add in-line code to the page, it s inserted in the HAHTtalk Basic source. However, you may want to make other additions to the code for a page for example, you might want to add an include statement, add some initialization code, or add variables to the page. The HTML editor s Server-side Code view lets you view the source code for a page, and lets you make additions, in predefined places, that will be preserved when the page is regenerated. (Note - you cannot change the generated source code; you can only add to it.) To view and add to the server-side code for a page 1 Open the page in the HTML editor. 2 Select View > Server-side Code, or click the Server-side Code view button. Here are some points to note: The white areas mark places where you can insert code. The grayed-out areas mark generated source code, which is read-only. If you make changes in Server-side Code view, and then return to Normal view or HTML Tags view, you will see your changes reflected. If the Server-side Code view button is disabled, be sure that you have saved the page (and that it is dynamic). For more information on this process, see the note that follows. Behind the scenes: How does Server-side Code view work? To keep from overwriting your additions, the IDE must keep your code separate from the code it generates. When you add code in Server-side Code view, your code is translated into HTML tags and kept in the project s HTML 52

74 Chapter 3: Working with HAHTtalk Basic Projects file for this page. If you look at the page in HTML tags view, you will see sections like this: <P><SCRIPT language="hahttalk-statement"><!-- Print date$--></script></p> When you build or publish the project, the code for the dynamic page is generated from the HTML file. What s in a HAHTtalk Basic page? When you publish a project, for each dynamic page, the IDE generates a file (pagename.hbs) that includes a constructor and an entry point for HS_pagename. The source code for each dynamic page has these contents. Note - Much of what you see in Server-side Code view for a HAHTtalk Basic page is generated for use by the IDE/IP s dialog boxes and can be ignored. In the example that follows, ellipses mark code that has been omitted. A place for include files Type definitions A page "constructor" A form handler An entry point for the page An exit handler An error handler The following sections explain each of these topics, using as an example the HAHTtalk Basic source for a page that simply displays the current date. A place for include files You can use the HAHTtalk Basic #include directive to include in a page one or more files that contain HAHTtalk Basic declarations. HAHTsite also supports a per-project Globals.hbs code page, which you can use to declare session global variables that can be accessed by all of the HAHTtalk Basic code in a project. (If this file is present in your project, its contents are automatically prepended to each.hbs file.) For more information, see Include files and Globals.hbs on page

75 Chapter 3: Working with HAHTtalk Basic Projects ' Generated by HAHTsite ' Includes. Includes can only be at the top of the file, ' and should not have code in them. ' Imports and includes. Type definitions The page defines two constants that can be useful in Print statements: Const HSQUOT = Chr$(34) Const HSCRLF = Chr$(13) & Chr$(10) HSQUOT produces quotation marks; use this constant when you want to embed quotation marks in a printed string. HSCRLF (carriage return/line feed) forces a line break in the HTML source file. (Remember that line breaks in HTML source files are ignored; if you want a line break in the displayed HTML, you will still need to add tags such as "<BR>" or "<P>...</P>".) You can add your own public or private variables, functions, or subroutines in the marked places of this section. For example, you might want to add a subroutine to be called as the success or failure page from a database action of a form button on this page. ' Type definitions. ' Privates ' Publish-code-generation helper variables - do not remove! Private Haht_TempJavaObj As Object ' Used for static-finals from Java Classes, temp java objects Private Haht_Page as Object Private HS_ShowDate_Construct_Called As Boolean ' User-defined private variables. ' More user-defined private variables. ' Private Functions and Subs ' User-defined private functions and subs. 54

76 Chapter 3: Working with HAHTtalk Basic Projects ' More user-defined private functions and subroutines. ' Public variables Const HSCRLF = Chr$(13) & Chr$(10) Const HSQUOT = Chr$(34) ' User-defined public variables. ' Public Functions and Subs ' User-defined public functions and subs. ' User-defined functions and subroutines. A page "constructor" This code is called the first time this page is browsed in a session. You can add custom code to the constructor. ' Constructor for page. Called once per page per state. Private Function HS_ShowDate_Construct() As Boolean On Error Goto HAHTErrorHandler_cons Dim aresponse As Object Set Haht_Page = Haht.getPage() HS_ShowDate_Construct = TRUE If (HS_ShowDate_Construct_Called) Then Exit Function Else HS_ShowDate_Construct_Called = TRUE End If... ' Custom constructor code. This code executes ' the first time a page is called. ' Custom initialization code ' for user-defined static variables. 55

77 Chapter 3: Working with HAHTtalk Basic Projects A form handler If your page contains one or more forms with buttons, then the Type Definitions section of your code will contain this line: #CONST HAHT_FORM_HANDLER_DEFINED=1 and the form handler code (enclosed by an #If statement) will execute. The generated code for a page s form handler adapts to the contents of the page. At runtime, when a user submits a form, the form handler determines which button was clicked and calls the appropriate command handler. In a HAHTtalk Basic project, you can create a custom form handler. You can also add your own code to process a Submit button, via the User Code choice in the button s Action field. For more information, see Chapter 8, Data-Agent Programming. 56

78 Chapter 3: Working with HAHTtalk Basic Projects #If (HAHT_FORM_HANDLER_DEFINED=1) Then ' Form handler Public Sub HS_ShowDate_fH Dim bcmdhandlercalled As Boolean Dim thepage As Object, theerrors As Object Dim aresponse As Object Set aresponse = Haht.getResponse() On Error Goto HAHTErrorHandler_fH bcmdhandlercalled = False If (Not bcmdhandlercalled) Then Set thepage = Haht.getPage() Set theerrors = thepage.geterrors() theerrors.add "Received form command did not _ invoke a command-handler", "form-handler" Set thepage = Nothing Set theerrors = Nothing HS_ShowDate End If HAHTExitHandler_fH: Exit Sub HAHTErrorHandler_fH: aresponse.addheaderline "Content-type: text/html" Print "" Print "<HTML><HEAD></HEAD><BODY><H3>" Print "The following error has occurred on page _ HS_ShowDate on line " & Str$(erl); If (Err.Source <> "") Then Print " of script " & Err.Source; End If Print ": <BR>" & Str$(Err) & " - " & Error & "<BR>"; Print "</H3></BODY></HTML>" Resume HAHTExitHandler_fH End Sub #End If An entry point for the page Each dynamic page has an entry point, named HS_pagename. This is the subroutine name you would use to call the page. The subroutine emits any header lines for example, Content-type: text/html 57

79 Chapter 3: Working with HAHTtalk Basic Projects Note that you can override the content-type header by another call to the Response object s setcontenttype method. See Adding content information to a header line on page 127. After emitting header lines, the subroutine then sets up the basic structure of the page, which would look like this in HTML: <HTML> <HEAD>...</HEAD> <BODY>...</BODY> </HTML> When you add in-line code to a page, it s added here, between the <BODY> and </BODY> tags. (However, for information about output that must go in the HTTP headers, see Writing headers on page 126.) ' Entry point for page Sub HS_ShowDate() ' Local variables Dim aresponse As Object Dim arequest As Object Dim out As Object On Error Goto HAHTErrorHandler ' Custom local variables. These are instantiated ' each time the page is run. ' Initialize local variables. Set aresponse = Haht.getResponse() Set arequest = Haht.getRequest() Set out = aresponse.getwriter() If (Not HS_ShowDate_Construct()) Then ' Constructor failed - exit page Exit Sub End If ' Custom initialization code. Executes before ' HTML tags are generated. ' Output HTTP response headers. ' Custom HTTP response headers. Add HTTP headers here. 58

80 Chapter 3: Working with HAHTtalk Basic Projects aresponse.addheaderline "Content-type: text/html" Print HSCRLF ' More custom HTTP response headers. ' Add HTTP headers here. ' Generate HTML for browser. print "<HTML>" & HSCRLF _ & "<HEAD>" & HSCRLF _ & " <META name=" & HSQUOT & "Generator" & HSQUOT & _ "content=" & HSQUOT & "HAHTsite 4.0" & HSQUOT _ & ">" & HSCRLF _ & " <TITLE>ShowDate</TITLE>" & HSCRLF _ & "</HEAD>" & HSCRLF _ & "<BODY>" & HSCRLF _ & " <P>" ; Print date$ print "</P>" & HSCRLF _ & "</BODY>" & HSCRLF _ & "</HTML>" ; ' All HTML has been generated. Put cleanup code here. Object references you can use The code shown above gets references to the Request and Response objects, as well as the default HtmlWriter. You can use arequest and aresponse to read values sent by the Web server or to write HTML. For example, to read a value passed in a form or on the URL, you would call arequest.geturlfield. This code also gets a reference to the default HtmlWriter. To write HTML output programmatically, you simply call the Print statement. You can also intermix text and in-line code on a page. In the HAHTtalk Basic source, the text turns into Print statements. For more information about these objects, see Chapter 5, HAHTsite Server Object Model. An exit handler In addition to a default error handler, each page has an exit handler label called HAHTExitHandler, which simply exits the subroutine. If you want to exit a page, you can write a GoTo HAHTExitHandler statement. 59

81 Chapter 3: Working with HAHTtalk Basic Projects HAHTExitHandler: Exit Sub An error handler Each dynamic page includes a default error handler and an On Error Goto statement that traps page-level errors. You can add code to the default error handler, and you can also include your own HAHTtalk Basic On Error construct in your subroutines. Your On Error construct will be nested inside the default error handler and will trap subroutine-level errors. HAHTErrorHandler: ' Handle errors that occur on the page. If (aresponse.getcontenttype() = "") Then aresponse.addheaderline "Content-type: text/html" Print "" End If ' Close any table tags that may be open. Print "</TABLE></TABLE></TABLE></TABLE></TABLE>" Print "The following error has occurred on page _ HS_ShowDate on line " & Str$(erl); If (Err.Source <> "") Then Print " of script " & Err.Source; End If Print ": <BR>" & Str$(Err) & " - " & Error & "<BR>"; ' Handle errors that occur on the page. Resume HAHTExitHandler Adding HAHTtalk Basic files to a project Another way to add server-side code to your project is to create a source file or import a source file or object file to be used by any of a project s dynamic pages. Code pages are source code files containing subroutines or functions written in HAHTtalk Basic. These subroutines and functions must have unique (project-wide) names, and they can be called by any of a project s dynamic pages. For example, the in-line code on an HTML page can call a subroutine to process some data. Or you can set a form s action to call a subroutine which either creates or calls a dynamic page. A subroutine can generate the binary 60

82 Chapter 3: Working with HAHTtalk Basic Projects data to display a picture or create a dynamic link and then print the link in an HTML anchor tag on the page. In a HAHTtalk Basic project, code pages are stored in the Web folder, usually in a subfolder. To add a new code page 1 Choose File > New > Code. 2 A blank code page opens in the workspace. 3 Enter HAHTtalk Basic subroutines or functions. For information about using the IDE s code editor, see Editing and compiling HAHTtalk Basic code on page 67. To import a code page In addition to creating new code pages in your project, you can import existing source code files. 1 In the project window, click on the folder in which you want to store the new file. 2 Choose File > Import File... The Import Files dialog appears. 3 Type or browse for one or more filenames. 4 Choose Copy Files or Create Shortcuts. If you want to maintain one central version of this file but use it in several projects, you may want to create a shortcut. 5 Click OK to complete the import. For more information about importing files into the IDE, consult the HAHTsite IDE and IP User s Guide, Chapter 3, Managing Projects. To save a code page 1 Select File > Save. The Save Code Page As dialog appears. 2 Type in a page name, or accept the default name. The suffix must be ".hbs". 3 To save the code page within the project, browse within the Project Items window for the folder name you want. 4 If the project is in source control, you will see an additional checkbox: Add to source control. Check this box to add this file to the source control system. 5 Click OK to save your changes. 61

83 Chapter 3: Working with HAHTtalk Basic Projects To save a code page outside the project To be called from within the project, a code page must be saved within the project. However, you can also save a code page to a file outside the project. 1 Select File > Save. The Save Code Page As dialog appears. 2 Click the Save to File... button. The Save As dialog appears. 3 Browse for a folder location and enter a filename. 4 Click OK to save your changes. Naming conventions for HAHTtalk Basic projects Code pages and dynamic pages represent entry points into the application s symbol table (.htx) file that HAHTsite creates when you publish a project. During the publish operation, HAHTsite converts dynamic pages into HAHTtalk Basic subroutines and prepends the characters HS_ to the resulting subroutine names. (Subroutine names in code pages are not changed.) The name assigned to a dynamic page s subroutine is determined as follows: The dynamic-page name is preceded with the characters HS_. Any illegal character that is, anything other than an alphabetic or numeric character is converted to the underscore (_) character. As a result of this conversion process, dynamic pages with similar names could be converted to subroutines with the same name. For example, the IDE converts the names 2-Page and 2 Page to HS_2_Page. Creating multiple pages that result in HAHTtalk Basic subroutines with the same name causes an error at publish time. To prevent this type of error, you can accept the default page names that HAHTsite provides. Or you can establish a page naming convention such that all dynamic page names consist of letters and numbers only. 62

84 Include files and Globals.hbs Chapter 3: Working with HAHTtalk Basic Projects The HAHTtalk Basic #include directive is similar to the #include directive used in C and C++. Here is a summary of the rules for using the #include directive and creating an include file. Rules for using an include file A file can have multiple #include directives. However, the directives must be at the top of a page, before any executable HAHTtalk Basic code. The #include directives must appear on a code page, not an HTML page. You can add #includes to an HTML page in Server-side Code view. (You can then access their contents from in-line expressions and statements on the HTML page.) Pathnames in the #include directives use HAHTsite project-style (UNIXstyle) directory delimiters ( / ). You can indent the #include directive with spaces or tab characters. However, the HAHTsite compiler will not recognize the directive if it is preceded by any characters other than spaces or tabs. Rules for creating an include file Include files use the.hbh extension. Include files must contain only declarations they cannot contain executable HAHTtalk Basic code. Include files can themselves contain #include directives (that is, nested includes are allowed). Project and external includes There are two versions of the HAHTtalk Basic #include directive: the project include and the external include. The project include The project include looks first for the included file in a project folder, then in an external (to the project) path. Its basic form is: #include "filename.hbh" which can include subfolder names. The compiler looks for the named file in these locations: 1 First, in the project folder containing the code page. 63

85 Chapter 3: Working with HAHTtalk Basic Projects 2 In the search path that you specified in the IDE s Tools > Options > General dialog. The path is a semi-colon separated directory list, which enables you to search several directories (in the order that the directories appear in the list). The default directory is HAHTsiteInstallDir/include. The HAHTsite compiler generates an error if it cannot find the include file in the project or in the include-directory search path. The external include The external include looks for the included file in an external path. Its basic form is: #include <file.hbh> which can include subfolder names as well. The compiler looks for the named file only using the include-file search path you specified the IDE s Tools > Options > General dialog. You can also use fully-qualified external directives. For example: #include <C:/HAHTsite/MyIncludeFiles/file.hbh> Declaring public variables with Globals.hbs You can declare a project s public (global) variables in a code page named Globals.hbs. A project can contain only one Globals.hbs, which can reside in any project folder. Its contents are automatically prepended to every dynamic page in the project. This file can contain project-wide constants and declarations in addition to global variables. Globals.hbs can contain only constants and variable declarations, not subroutines or functions. Because its contents become part of every dynamic page, be careful not to make the Globals.hbs file too large. You can always use #include directives to include files on a page-by-page basis. It s important to understand that each session gets its own copy of these global variables. They are not shared across sessions. Precompiler directives HAHTtalk code (whether on a code page or in the generated code for a dynamic page) can contain these standard precompiler directives: #Const #If...Then...#Else In addition, HAHTsite provides these predefined constants that can be used in an #If...Then...#Else directive: 64

86 Chapter 3: Working with HAHTtalk Basic Projects Constant PUBLISH_OS PUBLISH_WEBSERVER PUBLISH_SITENAME PUBLISH_SERVERGROUP Description The operating system to which this site is being published. Available only if this information has been entered in the Application Server administrator. If so, it appears in the site s.hsg file, like this: OSType=Windows:NT The name of the Web server for this site, as defined during Application Server installation or by the Web Server Utility. This name appears in the site s.hca file, like this: WebServerName=Netscape FastTrack 3.01 The name of the site to which you are currently publishing (i.e., the current site). This name includes the hostname. Here is an example: The name of the current server group, which appears in the Name field of the.hsg file, like this: Name=webapps Calling dynamic pages from HAHTtalk Basic When you build a HAHTsite project, the names of the project s dynamic Web pages are included as subroutines in the project s symbol table (.htx) file. The IDE automatically prepends HS_ to each page name, so that Page1.html would be stored in the symbol table as HS_Page1. From HAHTtalk Basic code, you can call a dynamic page as you would any subroutine, as in this example: Call HS_Page1 As with any subroutine, each dynamic page in a project must have a unique (project-wide) name. 65

87 Chapter 3: Working with HAHTtalk Basic Projects Event handling in a HAHTtalk Basic project In a HAHTtalk Basic project, initialization or termination methods are triggered when a session starts and when it ends. By default, these methods do nothing, but you can override them using the pseudo-methods HahtSessionOnStart and HahtSessionOnEnd. Here are the pseudo-methods: Method HahtSessionOnStart HahtSessionOnEnd Description Called when a new session is created, but before any pages are run. Should be declared as a function returning a boolean value. Called just before a session is destroyed. The system also calls this method after the application executes a HAHTtalk Basic STOP or END statement. Should be declared as a subroutine. HahtSessionOnStart In HahtSessionOnStart, you could populate a session recordset for use by subsequent pages in the session for example, you might want to read in the values of a database table (such as a catalog) that s used by several different pages. If HahtSessionOnStart fails, the Application Server terminates the session without running any pages. Note that HahtSessionOnEnd is not called if HahtSessionOnStart fails. There are two ways for HahtSessionOnStart to fail: It can return False, in which case the Application Server writes a runtime error message and terminates the session. You can edit HahtSessionOnStart to generate a page of diagnostic information if desired. Generally, after producing a diagnostic page, you want to prevent any further running of the session and any further error output from the Application Server, so you should also call End or Stop, which terminates the session. Here is an example: 66

88 Chapter 3: Working with HAHTtalk Basic Projects HAHTtalk Basic Function HahtSessionOnStart As Boolean Dim aresponse As Object Set aresponse = Haht.getResponse() aresponse.setcontenttype "text/html" aresponse.endheaders aresponse.write "Exiting the session <br>" aresponse.write "Failed in HahtSessionOnStart <br>" 'Terminate the session End End Function HahtSessionOnEnd Before terminating a session, the Application Server calls HahtSessionOnEnd (except in the case where HahtSessionOnStart has failed, as noted above). At this point, you might want to save the session state (for example), so that you can restore it later if the user returns to the application. Editing and compiling HAHTtalk Basic code This section explains the mechanics of writing HAHTtalk Basic code in the IDE: Using the code editor Compiling a HAHTtalk Basic application Working with application directories Using the code editor When you open a source file in the IDE s Code window, the Select object/select event combo boxes contain the names of the file s objects and events. 67

89 Chapter 3: Working with HAHTtalk Basic Projects To jump to an object or event in the source code Select its name from the appropriate combo box. To move to the next or previous event on the page Click the up or down arrow. To jump to a specific line of code 1 Click inside the source file (open in the code editor) and choose Edit > Go to... The Go to line dialog appears. 2 In the Line number field, enter the line number from the compiler s error message. 3 Click OK. The cursor s line number is displayed in the lower right-hand corner of the IDE s window. 68

90 Chapter 3: Working with HAHTtalk Basic Projects To hide (or make visible) the code on a page Select View > Code as Icon. All the code on the page is toggled between being shown as an icon and as text. To view more than one file in a split window Select Window > Tile. The files that are open in the workspace are tiled (to a maximum of four files), so that you can view one file while you re editing another. To display help for a HAHTtalk Basic keyword On the code page, highlight a HAHTtalk Basic keyword and press F1. Anywhere on a code page, you can press F1 to invoke the online help, which includes information about HAHTtalk Basic and the HAHTsite Server Object Model. To check the syntax of HAHTtalk Basic code You can check the syntax of a code file without running the compiler: With a page open in the code editor, choose Script > Check Syntax. (This option does not apply to pages open in Server-side Code view.) Compiling a HAHTtalk Basic application When you publish a HAHTtalk project, the IDE converts each dynamic page to an intermediate HAHTtalk Basic code (.hbs) file. Then it compiles all HAHTtalk Basic code, including code pages, generating binary (.hbb) files that it publishes to the project s application root directory. Note - If your project includes Java source files (for server-side Java that is called from HAHTtalk Basic), they are compiled at the same time. Finding compile-time errors If the HAHTtalk Basic compiler finds a syntax error in your code, it sends an error message to the project s Build/Publish window. In many cases, you can see what the problem is by looking at the error message. To navigate the compiler s error messages You can scroll through the messages in the Build/Publish window, double-clicking on any message with a + to expand it. 69

91 Chapter 3: Working with HAHTtalk Basic Projects Or you can choose Edit > Find Error > [First, Next, Previous, or Last] to go to that particular error in the Build/Publish window. To locate an error in your source code There are two ways to locate a particular compiler error: Double-click on the error message in the Build/Publish window. The IDE opens the file, if it s not open, and displays the relevant line. Click inside the source file (open in the code editor) and choose Edit > Go to... The Go to line dialog appears. In the Line number field, enter the line number from the compiler s error message. Then click OK. If the error is in your in-line code, rather than a HAHTtalk Basic code file, the IDE displays the source code for that page in Server-side Code view. Debugging a HAHTtalk Basic application HAHTsite includes a source-level debugger that lets you debug HAHTsite HAHTtalk Basic applications, even remotely. No special flag needs to be set to compile for debugging. For more information, see Chapter 15, Debugging Server-side Code. Note - If your application calls server-side Java from HAHTtalk Basic, the Java code will be skipped over during a debugging session. Working with application directories HAHTsite applications use four special directories: the staticroot directory, userroot, approot, and javaroot. You set these directory locations when you install the Application Server or when you modify its configuration. These root directories are shared by all applications within a particular server group, but you can differentiate between them by using the subdirectory macros %project% and/or %username%. (Otherwise, files from one project could overwrite files with the same name from another project.) Static root directory The static root directory is the directory where the Web server gets the application s static pages (.htm and.html files), graphics files, and any other files not run by the HAHTsite Application Server. Note - Secure static pages are stored in the approot directory. See Userroot, approot, and javaroot on page

92 Chapter 3: Working with HAHTtalk Basic Projects To retrieve the directory pathnames (in either NT or UNIX format, depending on the operating system), you would use code like this: Dim MyStaticRoot As String MyStaticRoot = HahtApplication.getStaticRoot() To retrieve the URL for the static-page directory, you would use code like this: Dim MyStaticURL As String MyStaticURL = HahtSession.getStaticURL() For more information about these methods and their uses, see Retrieving Application object properties on page 100. Userroot, approot, and javaroot The userroot, approot, and javaroot directories are used by the HAHTsite Application Server. userroot is the application s initial working directory. At runtime, a HAHTsite application has a current, or initial working, directory on the server. In your HAHTtalk Basic code, if you read or write a file by specifying just the file s name, the application looks for the file in the application s initial working directory. To retrieve this pathname, you can use code like this: Dim MyUserRoot As String MyUserRoot = HahtApplication.getUserRoot() approot, the application root directory, is the directory in which a HAHTsite Application Server finds an application s executable files (.htx,.hbb, and.hbx files). To check where the project s executable files were published, relative to the approot directory, you can use code like this: Dim MyAppDir As String MyAppDir = HahtApplication.getDirName() If the method returns \ or /, the files were published directly to the application root directory. Otherwise, the method returns the path to the subdirectory. (Note that this method does not return the full path to the application root directory.) javaroot, the Java class directory, specifies the location of any application-specific Java classes that you have developed. For more information about using server-side Java with your project, see Chapter 4, Calling Server-side Java from HAHTtalk Basic. 71

93 Chapter 3: Working with HAHTtalk Basic Projects Comparing HAHTtalk Basic and Visual Basic HAHTtalk Basic is fully syntax-compatible with Visual Basic. It is based on Visual Basic 3 and incorporates some features of Visual Basic 4. HAHTtalk Basic data types Scalars HAHTtalk Basic supports the following scalar data types. boolean (2 bytes) currency (8 bytes) integer (2 bytes) long (4 bytes) single (4 bytes) double (8 bytes) string (variable and fixed length) date (8-byte IEEE double) variant object Arrays Multidimensional arrays (of up to 60 dimensions) are supported. You can use REDIM to redimension arrays. Records Records in HAHTtalk Basic are declared using the TYPE statement. Names Variable names in HAHTtalk Basic: Must begin with a lowercase or an uppercase letter. Names cannot start with numbers, spaces, or hyphens. Must contain only letters, numbers, and the underscore character. Must not be longer than 80 characters. In contrast, Visual Basic names must not be longer than 40 characters. Scope HAHTtalk Basic variables follow the same scoping rules as Visual Basic variables and can be Public (global) or Private. Static variables are not supported. 72

94 Chapter 3: Working with HAHTtalk Basic Projects Subroutines and functions Subroutines and functions can be declared in the code blocks of any code pages. The scope of HAHTtalk Basic subroutines and functions is global by default. You can restrict the scope of a subroutine or function by using the Private keyword. A project s HAHTtalk Basic Executable file (.htx file) contains a dictionary that maps entry-point names to the appropriate HAHTtalk Basic object file. File I/O The HAHTsite Application Server supports the I/O mechanisms built into HAHTtalk Basic. These mechanisms include: various forms of sequential and random access to flat files SQL statements for accessing databases through ODBC and native access support for file and directory information, such as FileAttr, FileDate, FileLen, ChDir, ChDrive, CurDir, MkDir, RmDir, GetAttr, and SetAttr The HAHTsite Server Object Model provides methods for getting the pathnames of an application s static-page directory, dynamic-page directory, and initial working directory (see the section Working with application directories on page 70). Error handling HAHTtalk Basic supports the Visual Basic statements for error handling. Unhandled runtime errors will cause the HAHTsite Application Server to return an error page to the user. See the section An error handler on page 60 for more about using the HAHTtalk Basic On Error construct. Code page properties In the project window, you can set the properties of a code page. The General tab shows the page name and path (read-only). The Privileges tab lets you set the privileges required to access this code page. 73

95 Chapter 3: Working with HAHTtalk Basic Projects The Publish tab lets you specify whether or not the page should be published, whether it should inherit its publish properties from the parent folder, and whether it is exportable. The File tab displays the filename and characteristics as well as the project ID for this code page. 74

96 Calling Server-side Java from HAHTtalk Basic 4 Introduction...76 Using Java objects with HAHTtalk Basic...76 CreateJavaObject...77 GetJavaClass...78 CreateTypedJavaNull...78 Differences between HAHTtalk Basic and Java...79 Java is strongly typed...79 Parameter passing...80 Java is case sensitive...80 Locating objects...80 Mapping HAHTtalk Basic types to Java parameter types...81 Mapping Java types to HAHTtalk Basic types...83 Troubleshooting: Java runtime errors

97 Chapter 4: Calling Server-side Java from HAHTtalk Basic Introduction In addition to support for client-side JavaScript, Java applets, Java servlets, VBScript, and ActiveX, HAHTsite supports calling server-side Java from HAHTtalk Basic code with the HAHTsite Application Server s Java Virtual Machine. Server-side Java can be used on all the supported HAHTtalk Basic platforms. In addition to providing the inherent object-oriented benefits of encapsulation, inheritance, and polymorphism, Java integration lets you take advantage of JDBC, Java Beans, CORBA and the ever-growing supply of thirdparty class libraries. From your HAHTtalk Basic code, you can access Java classes as native objects simply declare Java objects as a HAHTtalk Basic data type, using either the CreateJavaObject or GetJavaClass calls. You can then access a Java class s methods and properties directly from your HAHTtalk Basic code. Java source files and class files are completely integrated into a HAHTsite project s hierarchy for easy editing, compiling, publishing, and integration with source control and configuration management systems. You can write the Java code for your Java source files (.java files) in the HAHTsite code editor, which provides syntax coloring for the Java language. For information about configuring Java compilers for your project, see the description of Tools > Options > Java Options in the HAHTsite IDE and IP User s Guide, Chapter 2, Using the IDE/IP s Windows and Toolbars. For information about creating and compiling Java files, see Editing and compiling Java code on page 37. Using Java objects with HAHTtalk Basic Creating and using Java objects with HAHTtalk Basic works much like creating and using COM/ActiveX objects. To create a Java object, you use the CreateJavaObject function instead of CreateObject. If you want to access a static variable or method of a Java class, use the GetJavaClass function. You can also obtain a null reference to a particular type of object using the function CreateTypedJavaNull. Occasionally, you may need such a reference for use as a parameter. Once you have a Java object in a HAHTtalk Basic variable of type Object, you access the Java object s properties and methods using the "." syntax. 76

98 Chapter 4: Calling Server-side Java from HAHTtalk Basic Here are descriptions of the two HAHTtalk Basic calls you use with Java. CreateJavaObject Syntax Function CreateJavaObject(className[, param1, param2, _...paramn]) As Object Description Creates an instance of the Java class specified in the classname parameter by calling the Java class s constructor and passing the additional parameters. Parameters Parameter Type Description classname String The case-sensitive name of the Java class. param1...paramn Variant Parameters to pass to the constructor of the Java class specified in the classname parameter. Example The following subroutine creates a Java object called MyCal from the class HTMLCalendar, which takes a month and a year as parameters. Then the calendar's GetMonthHTML method is called. This method returns an HTML string showing the days of the specified month. Sub printmonth(mymonth As Long, MyYear as Long) Dim MyCal As Object Set MyCal = CreateJavaObject("HTMLCalendar", MyMonth, MyYear) print MyCal.GetMonthHTML() Set MyCal = Nothing End Sub 77

99 Chapter 4: Calling Server-side Java from HAHTtalk Basic GetJavaClass Syntax Function GetJavaClass(className) As Object Description Returns a reference to a Java class without creating an instance of the class. Use this function to access the static properties and methods of a Java class. Parameters Parameter Type Description classname String The case-sensitive name of the Java class. Example Static methods and properties in Java are methods and properties that can be called without actually creating an object. For example, in Java the Math class has a static property that holds the value of PI. In Java code, you do not need to create a new Math object to access PI. You simply use Math.PI. In HAHTtalk Basic, you first need to get the class. Then you can access all the static members of the class. Here is an example. Sub printpi() Dim J As Object Set J = GetJavaClass("java.lang.Math") print J.PI PI is a static property of the Math class End Sub CreateTypedJavaNull Syntax Function CreateTypedJavaNull(className) As Object Description Returns a reference to an object of the type you specify in the classname argument. The reference will have been set to null. This reference is useful when you want to pass a value of null as a parameter to a method. The null must have a data type associated with it so that the Java Virtual Machine will recognize the method s signature. 78

100 Chapter 4: Calling Server-side Java from HAHTtalk Basic Parameters Parameter Type Description classname String The case sensitive name of the Java class to which you want a null reference. Example The following statements create a null reference to an object of type HTMLCalendar: Dim MyCal As Object Set MyCal = CreateTypedJavaNull("HTMLCalendar") These statements are the equivalent of the following statement in Java: HAHTCalendar MyCal = null; Differences between HAHTtalk Basic and Java The most important thing you should know when working with HAHTtalk Basic and Java is that there are important differences between the two languages data types, which are described later in this section. However, if you are an experienced HAHTtalk Basic programmer and are just starting to use Java, here are some other general things that are different in the two languages. Java is strongly typed In HAHTtalk Basic, many data types are automatically converted to the necessary type. For example: sub MyTest(Fred As String) print Fred End Sub sub YourTest MyTest 5 End Sub 79

101 Chapter 4: Calling Server-side Java from HAHTtalk Basic This HAHTtalk Basic code compiles and runs correctly because HAHTtalk Basic automatically converts the number 5 to the string 5 before passing it to the subroutine MyTest. Java is a strongly typed language it requires that data types match exactly. If a data type does not match, you will get compiler errors or runtime errors. Parameter passing In HAHTtalk Basic parameters are passed either by reference (ByRef) or by value (ByVal). Java has no equivalent specifier. Instead, Java determines how parameters are passed by examining their types: all primitive types (such as int and short) are passed by value; objects are passed by reference. Since Java is strongly typed, it is important that parameter and return-value types match. Java is case sensitive HAHTtalk Basic is case insensitive; the following subroutine calls are equivalent: Call YourTest Call yourtest Java is case sensitive. Method and property names must match case exactly. For example, if a Java class has a method called GetMyStuff, and you have a variable called J, J.getmystuff is not the same as J.GetMyStuff. Locating objects Java uses a class path to help find binaries (.class files) for a specific object. The class path is a semicolon (for Windows platforms) or colon (for Unix) separated list of directory names or zip file names. Java looks from left to right along the class path for a given class file name. For example, if the function CreateJavaObject("MyObject") is specified, then the Java VM does a casesensitive search for a file called MyObject.class along the path. All class names do not have to be immediately along the class path they can also be in subdirectories. For example, suppose the Java class path was set to C:\Fred and you want to create an instance of class found in C:\Fred\sub\myclass.class. To create an instance of the class, you would use the syntax CreateJavaObject("sub.myclass"). 80

102 Chapter 4: Calling Server-side Java from HAHTtalk Basic For information on setting the class path, see the Java Options section of the HAHTsite IDE and IP User s Guide, Chapter 2, Using the IDE/IP s Windows and Toolbars. Mapping HAHTtalk Basic types to Java parameter types The following table shows how HAHTtalk Basic types map to Java types when passed as parameters. HAHTtalk Basic Type Size (Bytes) Description Java Type Integer 2 Integer variables are used to hold numbers within the following range: <= integer <= String Arbitrary Strings are used to hold sequences of characters, each character having a value between 0 and 255. Strings can be any length up to a maximum length of characters. Long 4 Long variables are used to hold numbers within the following range: 2,147,483,648 <= long <= 2,147,483,647 short String object (java.lang. String) int Single 4 (32-bit) IEEE values A data type used to declare variables capable of holding real numbers with up to seven digits of precision. Single variables are used to hold numbers within the following ranges: float Negative: E38 <= single <= E-45 Positive: E-45 <= single <= E38 81

103 Chapter 4: Calling Server-side Java from HAHTtalk Basic HAHTtalk Basic Type Size (Bytes) Description Java Type Double 8 (64-bit) IEEE values A data type used to declare variables capable of holding real numbers with digits of precision. Double variables are used to hold numbers within the following ranges: Double Negative: E308 <= double <= E-324 Positive: E-45 <= double <= E38 Boolean 2 Represents the logical values of True (-1) and False (0) Boolean Date 8 (IEEE double values) A data type capable of holding date and time values. Date variables are used to hold dates within the following range: No equivalent January 1, :00:00 <= date <= December 31, :59: <= date <= Currency 8 A data type used to declare variables capable of holding fixed-point numbers with 15 digits to the left of the decimal point and 4 digits to the right. Object 4 byte ID Represents either a COM object or a Java object. No equivalent No equivalent for COM. Java object will map to appropriate Java object. User defined types Varies A typed defined by the user via the Type/End Type construct. No equivalent 82

104 Chapter 4: Calling Server-side Java from HAHTtalk Basic HAHTtalk Basic Type Size (Bytes) Description Java Type Array Varies An array of one of the above types. Not currently supported in HAHTsite Mapping Java types to HAHTtalk Basic types You can pass Java variables into your HAHTtalk Basic code. The following table shows how Java method and field (or property) types map into HAHTtalk Basic types. Java type Description HAHTtalk Basic type boolean unsigned 8 bits Boolean byte signed 8 bits Integer char unsigned 16 bits String of 1 character short signed 16 bits Integer int signed 32 bits Long long signed 64 bits No equivalent float 32 bits Single double 64 bits Double String String object String object Java object Object array of type T An array of some type Not currently supported in HAHTsite. 83

105 Chapter 4: Calling Server-side Java from HAHTtalk Basic Troubleshooting: Java runtime errors The table below lists Java runtime errors that are issued by the HAHTsite Application Server. The most common errors are 844 and 845. Error 844 (class not found) is typically caused by publishing to the wrong directory. Error 845 (method not found) is typically caused by a parameter mismatch. Error number Error text Typical reason(s) 844 Java class classname not found. 845 Method methodname not found or not public in Java class classname. 846 Field fieldname not found or not public in Java class classname. Class file is not on the class path. Wrong path to class given. Misspelling of class name (check case). Misspelled method name. Method is not declared public, so you do not have access to it. Parameter types you passed in do not match those of the method you specified. You need to refresh classes by restarting the Application Server. Misspelled field name. Specified field is not declared public, so you do not have access to it. You need to refresh classes by restarting the Application Server. 847 Cannot load the Java VM. Misconfiguration due to missing javai.dll (or javai.so), HSInspector.class, or classes.zip. Class path on Application Server could also be set up improperly. 848 Required HAHTtalk Basic Java class requiredclass not found. 849 The Java VM failed to load. Missing HSInspector.class file or class path does not specify the directory where HSInspector.class lives. Same reasons as

106 Chapter 4: Calling Server-side Java from HAHTtalk Basic Error number Error text Typical reason(s) 850 Cannot convert parameter parameternumber from a HAHTtalk Basic HAHTtalkBasicType to a Java JavaType. 851 Cannot convert a HAHTtalk Basic HAHTtalkBasicType to a Java JavaType. 852 Cannot convert a Java JavaType to a HAHTtalk Basic HAHTtalkBasicType. 853 Cannot convert return value from a Java JavaType to a HAHTtalk Basic HAHTtalkBasicType. 854 Cannot convert a HAHTtalk Basic array to a Java array. 855 No Java class path specified. Please specify one using the HAHTtalk Basic administrator. 856 Cannot create Java object. Maximum number (10,000) of Java objects reached. 857 The following Java exception was thrown: exceptionname&descr There is no supported Java type for the specified HAHTtalk Basic type for the specified parameter. There is no supported Java type for the specified HAHTtalk Basic type. There is no equivalent HAHTtalk Basic type for the specified Java type. There is no equivalent HAHTtalk Basic type for the specified Java type. Cannot pass HAHTtalk Basic arrays to Java methods. There is no class path configured for the Application Server. Each user can have a maximum of 10,000 Java objects in use at one time. A Java object threw the specified exception that was not handled in the Java code. 85

107 Chapter 4: Calling Server-side Java from HAHTtalk Basic 86

108 HAHTsite Server Object Model 5 Introduction...89 Built-in objects...90 Getting references to the built-in objects...91 From a Java project...91 From a HAHTtalk Basic project...96 The Application object...97 Application object methods...97 Application object variables...98 Multiple processes and application-level variables...99 Retrieving Application object properties Summary of Application object methods The Session object Session state Session timeout Event handling Creating a dynamic URL Creating a static URL Identification methods Summary of Session object methods The Request object Retrieving field values

109 Chapter 5: HAHTsite Server Object Model Retrieving cookie values Retrieving attachments Retrieving environment variables Summary of Request object methods The Response object Writing headers Setting cookies Writing the HTML output Summary of Response object methods

110 Introduction Chapter 5: HAHTsite Server Object Model HAHTsite s Server Object Model serves as a framework for a HAHTsite Web application. Using its built-in objects and methods, you can control the data passed to and from a Web browser client and get information about the application, the Web server, and the Application Server. If you look at HAHT_Intro s ShoppingCart.html page (part of which is shown above), you can see two common uses of the built-in objects: retrieving data passed in the URL field, and calling a subroutine to store data in variables, to be shared across pages in a session. With the Server Object Model you can also perform operations such as: sharing variables across sessions, as well as across pages. setting and retrieving the values of one or more cookies. enforcing page sequence in a session. If your application requires that a user visit pages in a particular order for example, users must fill out a form on one page before they can view another page you can check for and enforce this requirement. managing the lifetime of a session, by controlling session timeouts. This chapter describes the Server Object Model s built-in objects, which provide most of the functionality described above, and more. For information about controlling access to secure-static and dynamic pages, by setting and 89

111 Chapter 5: HAHTsite Server Object Model checking page and session privileges, see Chapter 12, Access Control. For information about creating CORBA clients and servers, see Chapter 14, HAHTsite CORBA Capabilities. Built-in objects From What s in a Java page? on page 18, and What s in a HAHTtalk Basic page? on page 53, you should already be familiar with the Page object. In a Java project, every dynamic page created in the IDE is a subclass of Page, called Hspagename. In a HAHTtalk Basic project, each page is a subroutine, called HS_pagename. You can also create dynamic pages programmatically, by implementing the HAHTPage interface (in Java) or by creating a HAHTtalk Basic subroutine to display a page. In addition to Page objects, each HAHTsite application contains several builtin objects. You don t need to (and should not!) create the Server, Application, and Session objects; all you need is references to them. Each application also has built-in Request and Response objects; however, for special purposes you may want to create your own Request and/or Response object. The com.haht.haht class contains methods that will return a reference to your application s built-in objects; see Getting references to the built-in objects on page 91. The built-in objects are derived from the com.haht.hahtobject class, as shown in the tree below: HahtObject Application (implements ApplicationListener) GeneratedApplication HahtApplication HahtEvent Page (implements HAHTPage) Request Response Server Session (implements SessionListener) GeneratedSession HahtSession The Server object contains get and put methods for storing variables shared among applications, as well as event handling methods. There is a single Server object for each hsserver process in the Application Server. The Application object has information about the current application. There is only one Application object, which may be shared by many clients simultaneously. 90

112 Chapter 5: HAHTsite Server Object Model The Application object contains methods that return information about the current application, as well as event handlers that are triggered when the application has just started or is about to end, or when a session is about to start or has just ended. Like the Server object, it has get and put methods for storing application-level variables. The Session object contains information about the current session, which is defined as a browser client using the application. There is a separate Session object for each client. It contains methods to retrieve information about the current session, such as session privileges; methods to create URLs; and methods to control the session timeout. It also has two event handlers, onstart and onend, that are called when a session is created and just before it s destroyed. Like the Server and Application objects, it has get and put methods for storing application-level variables. You use the Request object s methods to retrieve data the client browser sends to the Web server. For example, when a user completes a form and presses the submit button, the form data is sent to the Web server, either on the URL or in a separate packet. The Request object has geturlfield methods to retrieve these values. You use the Response object s methods to generate HTML that the Web server sends to the browser, including methods to write HTML output and set cookies. Note - The HahtEvent class is the parent class for applicationand session-level event handlers. For more information, see Event handling in a Java project on page 31 and Event handling in a HAHTtalk Basic project on page 66. Getting references to the built-in objects Depending on whether you are developing a Java project or a HAHTtalk Basic project, you will use different methods to get references to the Server Object Model s built-in objects. From a Java project When you create a new Java project, the IDE creates a HahtApplication class and a HahtSession class, as subclasses of GeneratedApplication and 91

113 Chapter 5: HAHTsite Server Object Model GeneratedSession, respectively. You can add variables and methods to these classes and reference them from each dynamic page. Application and Session references in a dynamic page In a Java project, the generated code for a dynamic page defines two variables, hahtapplication and hahtsession, to refer to the Application and Session objects: Java protected HahtApplication hahtapplication; protected HahtSession hahtsession;... hahtapplication = (HahtApplication) Haht.getApplication(); hahtsession = (HahtSession) Haht.getSession(); Both hahtapplication and hahtsession are set in the constructor for the page, so their values are accessible anywhere in the code for that page. For example, if you have declared a variable lastname in HahtSession.java, this is how you would refer to it on a dynamic page: hahtsession.lastname Application and Session references in other Java source files In a Java source file other than a dynamic page, there are two ways to get a reference to the Application or Session object. If you simply need to use a method defined for the Application or Session class, you can use this procedure: 1 Get a reference to the current application or session, using Haht.getApplication() or Haht.getSession(). 2 Use that reference to access the variable or method. For example, you can get a URL string, given a project ID: Java String myurl = Haht.getSession().getURL ("89392C87BB91D A02550C10000"); However, you may also need to access variables and methods that you have added to HahtApplication.java or HahtSession.java. In that case, you must use the second procedure, which is actually a superset of the first. (This 92

114 Chapter 5: HAHTsite Server Object Model is the procedure used to define hahtsession and hahtapplication on dynamic pages.) 1 Get a reference to the current application or session, using Haht.getApplication() or Haht.getSession(). 2 Cast the return value to type HahtApplication or HahtSession. 3 Use that reference to access the variable or method. For example, suppose that in the code for a dynamic page, you want to print the value of a variable you ve stored in the Application object. Your code would look something like this: Java HahtApplication myapp = (HahtApplication)Haht.getApplication(); out.print(myapp.myvar); Session references in master projects and referred projects Both master projects and referred projects contain GeneratedSession.java and HahtSession.java files; however, in a master project, the class GeneratedSession extends com.haht.project.session, while in a referred project, the GeneratedSession class extends the class com.haht.project.utilitysession (see the figure below). The important point to note here is that the UtilitySession class does not represent a user session, as Session does; UtilitySession is a very general class from which GeneratedSession inherits only a small amount of functionality. 93

115 Chapter 5: HAHTsite Server Object Model com.haht.project.session com.haht.project. UtilitySession GeneratedSession GeneratedSession HahtSession HahtSession Master Project Referred Project In a master project: A Session object represents an entire session. A GeneratedSession object contains master-project extensions to the Session class such as references to objects that have been dragged and dropped onto the project s Session folder. For example, the GeneratedSession object might contain a reference to a data agent representing a session recordset created by dragging and dropping a table onto the Session folder. A HahtSession object contains user-defined variables and methods. A referred project s GeneratedSession and HahtSession objects are analogous to those in a master project. However, a referred project has no Session object associated with it. There is only one Session object per user session. How do you get references to these objects? HAHTsite generates the code that obtains references to these objects and assigns those references to variables. The matrix below shows the names you use to access objects in either a master project or a referred project from either a master project or a referred project. 94

116 Chapter 5: HAHTsite Server Object Model Name hahtsession projectname_hahtsessionext Use In a master project, you should use this name to refer to the session s Session object. You can also use it in a master project to refer to the master project s GeneratedSession and HahtSession objects, but you shouldn t do this if your project is, or might later become, a referred project. HAHTsite provides another name to use in this situation. In a referred project, you can only use the name to refer to the session s Session object. In a master project, you can use a name of this form to refer to the master project s extended objects (its GeneratedSession and HahtSession objects) and to a referred project s extended objects. (The projectname portion of the name will vary depending on the project.) In a referred project, you use a name of this form to refer to the referred project s extended objects. Briefly, here s how you might use these names. Suppose that from your master project, you want to refer to a session recordset (a data agent) defined in the referred project ReferredProject. For the purposes of this example, assume that the session recordset was created by dragging a shared query named SharedQuery to the project s Session folder. You could refer to this data agent using the following code: protected com.haht.project.datamanager.dataagent da1 = ReferredProject_hahtSessionExt.getSharedQuery(); Request and Response objects The run method for each page takes two arguments: arequest and aresponse, which refer to the Request and Response objects, respectively. You can use these references if you add code to a dynamic page either by adding in-line code to the HTML page, or by adding to the generated code in Server-side Code view. You can also call the Haht object s getrequest and getresponse methods: 95

117 Chapter 5: HAHTsite Server Object Model Java Request myrequest = Haht.getRequest(); Response myresponse = Haht.getResponse(); Page object The Session object s returnhahtpageobject method instantiates a page object and returns a reference to it; if the page has already been instantiated, it simply returns the object reference. For details, see Calling a dynamic page from Java on page 30. From a HAHTtalk Basic project In a HAHTtalk Basic project, the Server Object Model contains three predefined constants: haht a reference to the com.haht.haht object hahtapplication a reference to the current Application object hahtsession a reference to the current Session object (As with other HAHTtalk Basic identifiers, the names for these constants are case insensitive.) You can use these references anywhere in the code for a dynamic page. For example, to retrieve the state ID for the current session, you would use code like this: HAHTtalk Basic Dim sstateid as String Set sstateid = hahtsession.getstateid() On code pages, you can use the Haht object s getapplication and getsession methods to get references to the Application and Session objects, like this: HAHTtalk Basic Dim MyApp As Object Set MyApp = Haht.getApplication() Dim MySession As Object Set MySession = Haht.getSession() 96

118 Chapter 5: HAHTsite Server Object Model Request and Response objects The generated code for a page gets references to the Request and Response objects in this way: HAHTtalk Basic Dim arequest As Object Dim aresponse As Object Set arequest = Haht.getRequest() Set aresponse = Haht.getResponse() You can use these references if you add in-line code to a page, or if you add code in Server-side Code view. On a separate code page, you can call the getrequest and getresponse methods. The Page object In a HAHTtalk Basic project, you refer to a page, or call a page, simply by its name (recall that dynamic pages in the IDE have the prefix HS_ ). The Application object The Application object contains information about the current application. There is only one Application object, which may be shared by many clients simultaneously. On the other hand, there is a separate Session object for each client using the same application. Note - If you have configured the Application Server to run multiple processes, there will actually be one Application object per process. See the technical note Multiple processes and application-level variables on page 99. Application object methods The most commonly-used Application object methods can be divided into these types: Type Methods dealing with application variables Refer to Application object variables on page 98 97

119 Chapter 5: HAHTsite Server Object Model Type Methods to get the properties of the Application object Refer to Retrieving Application object properties on page 100 In addition, to read about access control methods, see Chapter 12, Access Control. For information about CORBA, see Chapter 14, HAHTsite CORBA Capabilities. Application object variables In a Java project, you can store application-level variables directly in the HahtApplication class. The Application class also has get and put methods that you can use to create variables on the fly. In a HAHTtalk Basic project, you can use the get and put methods for application-level variables; this can be particularly useful in HAHTtalk Basic applications that call server-side Java, as a way to share variables. Get, put, and remove The put method associates a name with an object and stores the name/value pair in the Application object. The get method retrieves the stored value. There is also a remove method, that removes the object reference. In a Java project, the value you put must be an object; when you call get, you must cast the return type appropriately. In a HAHTtalk Basic project, the value you put can be an object or a string; the type conversion is done automatically on a get. Calling get for a variable that doesn t exist returns a null object. Examples: Java String s = "Hello world"; hahtapplication.put("myvar", s); // Get the value we just put String s2 = hahtapplication.get("myvar"); 98

120 Chapter 5: HAHTsite Server Object Model HAHTtalk Basic Dim O as Object hahtapplication.put "myvar", "Hello world" Get the value we just put Set O = hahtapplication.get("myvar") If O is not Nothing Then Print O Else Print "Variable not set" & "<br>" End If Variable locking If you are updating a variable that belongs to the Application object, it s a good idea to lock the application s variables until the operation has completed. Suppose you are updating several related variables, such as database access information. Because they are related, you don t want any other sessions to access them until they have all been updated. In your program, you would lock the Application object s variables each time you access them. If another session has the variables locked, your session waits until the other session calls the unlock method. Note that these methods work only if every access to those variables calls lock and unlock. In pseudocode: Call lock (if the Application object s variables are locked by another session, waits until they are unlocked) Update variables Call unlock If your program doesn t explicitly call the unlock method, the Application Server will unlock the Application object s variables when the page ends or times out. Multiple processes and application-level variables What is the scope of an Application object s variables? You can use the Application object to share variables across multiple sessions. However, it s important to understand that, depending on your Application Server configuration, an application may be running in several processes, each with its own Application object and set of Session objects. See the drawing below, showing four processes running on two Application Servers. Each session can access the variables stored in the Application object, but only for that particular process. There is no communication between processes. 99

121 Chapter 5: HAHTsite Server Object Model You can use the Application object to cache variables for use by multiple sessions as you could see in the Java example that printed the current number of sessions ( Example: onsessionstart, onsessionend on page 33). In that example, an application-level variable, nactivesessions, kept count of the number of active sessions. But since variables cannot be shared across processes, each process would have its own copy of the nactivesessions variable. Retrieving Application object properties The Application object provides a number of methods for retrieving properties such as its name, directory name, or initial working directory. One commonly-used method is getappdata, which returns the value of an application property. For example, to get the dynamic URL, you would use this code: Java String myurl = hahtapplication.getappdata(0, "DynamicURL"); 100

122 Chapter 5: HAHTsite Server Object Model HAHTtalk Basic Dim MyURL As String MyURL = hahtapplication.getappdata(0, "DynamicURL") This URL is determined by a project s site properties, where it appears as the Dynamic-hsrun URL (seen below). You can use it as the prefix for URLs to applications. The first argument to getappdata is a subsite index. Site definitions, which exist at the project level, can contain definitions of subsites which will apply to certain project items. For example, you might want to publish part of a project to a secure Web server (one that supports the HTTPS protocol). Or you might want to include Perl scripts in a HAHTsite project and publish them directly to the Web server s cgibin directory. For more information about subsites, see the HAHTsite IDE and IP User s Guide, Chapter 4, Working with Sites. In a project without subsites, the site definition becomes the default subsite definition. In this case, use zero as the subsite index. The second argument is the property whose value you want returned. It can be one of the following: 101

123 Chapter 5: HAHTsite Server Object Model Field "AppendString" "DynamicURL" "HSrunAppendString" "HSrunExtension" "HSrunParamDelimiter" "StaticROOT" "StaticURL" "ProjectSubDir" 1 "SubSiteName" Description String (if any) this subsite s Web server appends to the URL of a dynamic page. Example:? URL for the directory defined by the Web server s CGI alias. Example: String (if any) this subsite s Web server appends to the HSrun command. String (if any) this subsite s Web server expects the HSrun executable to have. Example:.hse Character used as a delimiter between parameters passed on the URL. Example: & Path to subsite s document root directory. Example: \\moe\d\netscape\suitespot\docs URL to default subsite s document root directory. Same as getstaticurl. Example: Project subdirectory under application root directory. Example: %project% Subsite name associated with index (zero-based). Same as getsubsite. Example: default 1. For compatibility with past releases, SubDirURL can be substituted for ProjectSubDir. Summary of Application object methods The following table lists the methods available with the Application object (with the exception of methods related to access control and CORBA, which are covered in later chapters). For a fuller description of each method, consult the on-line help for the Server Object Model. 102

124 Chapter 5: HAHTsite Server Object Model Note - When a file system pathname is returned (rather than a WWW URL), its format is operating system-dependent. For example, for an NT system, getdirname would return \subdirectory\, while for a UNIX system, it would return /subdirectory/. Method addapplicationlistener get getappdata getdirname getname getpathname Description (Java only). Adds an event listener to the Application Event Listener. Retrieves the value of a name/value pair stored in the Application object (see put). The value is returned as an Object and, in Java, must be cast to the appropriate class. Depending on the fieldname argument, returns information about the application for the given subsite. Directory part of HAHTsite executable file pathname, relative to the application root directory. NT example: \JSimple\ UNIX example: /Jsimple/ This value is useful for accessing user data files that are organized in the same manner as the application; the data files will be in a parallel subdirectory with the same name under the Userroot directory. Note, however, that this directory is relative to the configured Application Root directory. Thus, what is returned as / here may indeed be usr/local/webapp/approot. Application name without extension or path. Example: Test Full pathname of HAHTsite executable file. NT example: \JSimple\Test.htx UNIX example: /JSimple/Test.htx 103

125 Chapter 5: HAHTsite Server Object Model Method getstaticroot getstaticurl getstring getsubsite getsubsitecount Description Path to Web server s document root directory for the default subsite. The document root directory is where the Web server stores its static pages. NT example: \\moe\d\hahtsite\doctree UNIX example: /usr/local/hahtsite/doctree URL to default subsite s document root directory. Example: Retrieves the value of a name/value pair that is a string stored in the Application object. See putstring. Subsite name associated with index (zerobased). Example: default Number of subsites defined for the application, including the default subsite. 104

126 Chapter 5: HAHTsite Server Object Model Method getuserroot Description Path to application s initial working directory (operating system dependent). If your code reads or writes a file without specifying an absolute path, the application looks for the file in the application s userroot directory. Files that a user attaches to a form (using File Upload) are also placed in userroot. When you install the Application Server or modify its properties, you set the userroot Transfer URL (shown in a site definition below), which defaults to HAHTsiteInstallDir\userroot. If you publish your project to a subdirectory, the subdirectory s name is appended to the userroot path (for example, \\moe\webdocs\userroot\myproject). Dynamic - server group: Server Group Host: moe.haht.com Server Group: webapps File: d:\hahtsite\sites\cache\moe.haht.com \webapps.hsg Subdirectory: %project% State IDs in: Cookies Location: approot Transfer URL: \\moe\webdocs\approot Location: userroot Transfer URL: \\moe\webdocs\userroot Location: javaroot Transfer URL: \\moe\webdocs\javaroot isbasicapp isjavaapp isrecordingpagevisits isusingcookies Returns true if this is a HAHTtalk Basic application. Returns true if this is a Java application. Returns true if sessions of this application are recording a history of pages visited. Returns true if the application was published to use cookies (based on the site definition). For more information about setting the use Cookies/use URL property, see the HAHTsite IDE and IP User s Guide, Chapter 4, Working with Sites. 105

127 Chapter 5: HAHTsite Server Object Model Method lock onsessionstart, onsessionend onstart, onend put putstring remove removeapplicationlistener startrecordingpagevisits, stoprecordingpagevisits unlock writelog Description Acquires a lock for the Application object s variables. Event handler called when a new session is created, or right before a session is destroyed. In a Java project, can be customized in HahtApplication.java. (Not accessible in HAHTtalk Basic projects.) Event handler called when the application has just been created or just before it is terminated. In a Java project, can be customized in HahtApplication.java. (Not accessible in HAHTtalk Basic projects.) Associates an object with a name and stores the name/value pair in the Application object. See get. Associates a string value with a name and stores the name/value pair in the Application object. See getstring. Removes the association of the named variable with a value. Applies to name/value pairs created with put or putstring. (Java projects only). Removes an event listener from the list of Application listeners. Tells the Application Server to begin/stop recording a history of pages visited. To retrieve this history, use the Session object s getpagesvisited method. Releases the lock for the Application object s variables. Writes a string to the Application Server s log file. 106

128 The Session object Chapter 5: HAHTsite Server Object Model Unlike the Application object, a Session object applies to a single user. When a browser initially requests a Web page, the Application Server creates a Session object unless one has already been created for that user. A Session object continues to exist until it s terminated by the Application Server (see Session timeout on page 108). Like the Application class, the Session class has get and put methods that you can use to create variables on the fly, and it has lock and unlock methods that let you serialize access to session-level variables (see Variable locking on page 99). In a Java project, you can also edit HahtSession.java directly, to declare and set variables as well as to add event handlers. In a HAHTtalk Basic project, you can use include files or store variables in the globals.hbs file. (Note that variables are not shared across sessions in a HAHTtalk Basic project.) For more information, see Include files and Globals.hbs on page 63. Session-related topics covered in this chapter include: Topic Reference Session state Session state on page 107 Session timeout Session timeout on page 108 Event handling at the session level Event handling on page 108 Creating a URL for a project item or for a location outside the project Determining whether this is the first page of a session; identifying the current method/subroutine or the calling method/subroutine Creating a dynamic URL on page 109 Identification methods on page 113 You may also be interested in the explanation of session privileges and access control in Chapter 12, Access Control. Session state There are two important concepts to understand at the session level: state and timeout. 107

129 Chapter 5: HAHTsite Server Object Model State is the collection of information available to an application. Typical Web applications are inherently stateless, meaning that they don t retain information between pages. In HAHTsite, Session objects maintain state even if the user moves to other Web pages, until the session times out. This means that you can store session-level variables in the Session object and access them from multiple pages. One use for session-level variables is to store information about user preferences. Another is to store a recordset returned by a database command. You can then access the recordset across page boundaries a great efficiency. (For details, see the HAHTsite IDE and IP User s Guide, Chapter 15, Connecting to a Data Source. ) Session timeout When a user leaves a Web application, how does the application know? There is no quit or exit button, and in fact the user might return after browsing other pages. On the other hand, you wouldn t want to keep a session alive indefinitely it would eat up your resources. The answer lies in the Application Server, which controls the session timeout that is, how many seconds must elapse, with the application idle, before the Application Server terminates the session. The default timeout value is 300 seconds, set in the Application Server configuration. However, you can override this default for the current session. Here are the applicable methods: The settimeout method sets the timeout value for the current session. The gettimeout method returns the number of seconds before timeout occurs. (There is also a keepalive method, which resets the timeout value; this method is useful only when you are accessing CORBA objects.) In addition to these methods, in a HAHTtalk Basic project, you can call Stop or End to immediately stop execution of the application. In a Java project, you can call the Session object s abandon method. Event handling When a session ends, HAHTsite automatically performs cleanup tasks such as closing any open data source connections, destroying OLE and Java objects, and freeing memory. However, you may want to save the session state, so that you can restore it if the user logs back in. Or you may want to perform certain initialization procedures when a session begins. The Session object includes onstart and onend event handlers that you can customize (in Java) or override 108

130 Chapter 5: HAHTsite Server Object Model (in HAHTtalk Basic). Refer to Event handling in a Java project on page 31, or Event handling in a HAHTtalk Basic project on page 66. Creating a dynamic URL The Session object provides several methods for building a URL that you can use to link from a dynamic page to another page, to an image, or to an image map. These methods require either a project ID or a string representing the page, image, or image map. Building a URL from a project ID The geturl method locates a project item a page, an image, or an image map by means of its project ID and returns a string containing a URL for that item. The geturl method has a number of variations, with different parameters, including: project ID a universally unique identifier that HAHTsite assigns to a project item. Within the IDE, you can view a project item s ID by clicking on the item, choosing Edit > Properties and clicking the File tab. default string a string that is to be returned if the method fails to locate the item. This can occur if a project item was deleted but is still referenced somewhere in the source code. If you don t specify a default string and the method fails, it returns an empty string. append string a bookmark or query string to be appended to the generated URL. A bookmark consists of the pound sign (#), followed by the string for a bookmark anchor. A query string should contain one or more name/value pairs, separated by ampersands for example, Name=Johnson&City=London. method (Java only) the method to be run on the destination page. The method defaults to run. This argument is disregarded in HAHTtalk Basic projects. wantfullurl a boolean value; if true, the method returns a complete URL, rather than a relative URL. You might set this value to true to produce a string to redirect users to another dynamic page. Some browsers require full URLs in this case. A full URL would look something like this: TbOIpYMPgKipKLh90G357_Ws_T/HAHTpage/PJ2.HsPageTwo.run 109

131 Chapter 5: HAHTsite Server Object Model while a relative URL might look like this for the first dynamic page: StateId/TbOMAYMPp5MpKLxZ0G3xK_WCL1/HAHTpage/PJ2.HsPageTwo.run and like this for subsequent dynamic pages:../hahtpage/pj2.hspagetwo.run Note that if state IDs are being passed in cookies, rather than on the URL, you will not see a state ID in the URL string returned. The default for this argument is false that is, relative URLs. wantstarturl a boolean value; if true, the method returns a URL for calling the page from a static page, including the.htx or.hjx file and the start= string. It does not include a state ID, and it does start another session instance. If you set wantstarturl to true, you will always get a full URL, regardless of the setting for wantfullurl. Here s an example of the string returned: PJ2.hjx;start=PJ2.HsPageTwo.run The default for this argument is false. Example: Building a URL This example programmatically builds an anchor tag and target URL for a dynamic page, using relative URLs (the default). The example calls geturl, passing it the project ID for the destination page. Then it inserts the return value in an anchor tag. Java String myurl = hahtsession.geturl ("74FC8E62E969D C10000"); out.print("<a HREF=\"" + myurl + "\"> Page2 </A>"); HAHTtalk Basic Dim MyURL As String MyURL = hahtsession.geturl("74fc8e62e969d c10000") Print "<A HREF=" & HSQUOT & myurl & HSQUOT & "> Page2 </A>" At runtime, geturl adds the correct CGI delimiter (such as? ), depending on the target Web server. If the call is being made from the first dynamic page of the application, then geturl returns a URL containing the state ID (if state IDs are being passed in URLs rather than cookies); the HTML for the anchor tag looks similar to this: 110

132 Chapter 5: HAHTsite Server Object Model <A HREF="StateId/T6SYOI8X3hdVAmTIbusmwsZ- NK/HAHTpage/MyProject.HsPageTwo.run?"> PageTwo </A> If this isn t the first dynamic page in the sequence, then geturl returns a relative URL, and the HTML looks like this. <A HREF="../HAHTpage/MyProject.HsPageTwo.run?"> PageTwo </A> (This is the output from a Java project; in a HAHTtalk Basic project, it would look the same, except that HsPageTwo.run would be replaced by HS_PageTwo. ) If the Web server has been defined as storing state information in cookies, then the state ID is passed in a cookie instead of on the URL. For more information about cookies and Web browsers, see the HAHTsite IDE and IP User s Guide, Chapter 4, Working with Sites. Creating a dynamic URL for an image map, page, or file In addition to the geturl method, there are three methods that return a dynamic URL for an image map, a dynamic page, or a file (for example, a secure static page), without requiring the project ID as an argument. Instead, you supply a string containing the name of the page, image map, or file. (There is a second, optional argument: the name of a subsite.) These URLs can refer to elements outside the project, or even to elements that don t yet exist (for example, files you will later copy to the approot directory). HAHTsite doesn t check on the validity of the URL it creates; it simply accepts the input you supply and creates a URL by adding the state ID and the CGI delimiter for the Web server you re publishing to. createpageurl creates a URL for a dynamic page. In a Java project, its argument is the page s fully-qualified run method that is, packagename.classname.run. In a HAHTtalk Basic project, its argument is the name of the page subroutine (HS_pagename). This code returns a dynamic page URL. Java String mypageurl = hahtsession.createpageurl("myproject.hspagetwo.run"); HAHTtalk Basic Dim MyPageURL As String MyPageURL = hahtsession.createpageurl("hs_pagetwo") 111

133 Chapter 5: HAHTsite Server Object Model createmapurl creates a URL for an image map. Its argument is the filename for a dynamic server-side image map (.hmp). This example displays a dynamic image map ( MyMap.hmp, based on an image Globe.gif ). It calls two Session methods: one to create a dynamic map URL, and one to create a static URL (for more information on that method, see Creating a static URL on page 113). Java out.print("<p><a href=\"" + hahtsession.createmapurl("myimagemap.hmp", "default") + "\"><img src=\"" + hahtsession.createstaticurl("globe.gif", "default") + "\" border=\"0\" height=\"128\" width=\"144\" ismap></a></p>"); HAHTtalk Basic Print "<P><A href=" & HSQUOT & _ hahtsession.createmapurl("mymap.hmp", "default") _ & HSQUOT & "><IMG src=" & HSQUOT & _ hahtsession.createstaticurl("globe.gif", "default") & _ HSQUOT & " border=" & HSQUOT & "0" & HSQUOT & " height=" _ & HSQUOT & "128" & " width=" & HSQUOT & "144" & HSQUOT & _ " ismap></a></p>" & HSCRLF createfileurl creates a URL for a file stored in the approot directory, such as a secure static page. This code returns a URL for a secure static page. Java String myfileurl = hahtsession.createfileurl("mysecurepage.html"); HAHTtalk Basic Dim MyFileURL As String MyFileURL = hahtsession.createfileurl("mysecurepage.html") 112

134 Chapter 5: HAHTsite Server Object Model Creating a static URL One additional method creates a URL for a static page; its arguments are the name of the page and, optionally, a subsite name. Given a null page name, it returns the URL for the staticroot directory. Suppose your site is called and you want to create an HTML anchor with the destination of You would use code like this: Java String mystaticurl = hahtsession.createstaticurl("staticpage.htm"); out.print("<a HREF=\"" + mystaticurl + "\"> Static page </A>"); HAHTtalk Basic Dim MyStaticURL As String MyStaticURL = hahtsession.createstaticurl("mystaticpage.htm") Print "<A HREF=" & HSQUOT & MyStaticURL & HSQUOT & "> StaticPage </A>" Identification methods The Session object has additional methods for purposes such as finding out if this is the first dynamic page of the session, and finding the name of the calling routine. isnewapp The isnewapp method returns true if this is the first dynamic page of a session. One simple use for this method is to conditionally display a welcome message when a user first invokes an application. It can also be used to control how a page generates URLs in a case where the user can return to the start page via a text anchor. 113

135 Chapter 5: HAHTsite Server Object Model whoami and whocalledme The whoami method returns the name of the current method or subroutine. If you were placing a clip on a number of different pages, you could call whoami within the clip to customize some part of the output, depending on the current page. The whocalledme method returns the name of the calling method or subroutine. You might invoke whocalledme in a general-purpose method or subroutine that might be called by several different pages. Summary of Session object methods This table summarizes the methods of the Session object. It does not include methods for access control or for CORBA, which are described in later chapters. For particulars, consult the online help for the Server Object Model. Method abandon addsessionlistener auditmessage auditpage callbyprojid createfileurl createmapurl createpageurl createstaticurl endauditing get Description Terminates the session after the page completes. (Java projects only). Adds an event listener to the Session Event Listener. Writes a message to an audit file keyed to a hit number. Turns on session auditing for the current page. The audit files contain information about requests and responses and user-generated auditing messages. Calls a dynamic page, given its project ID. Returns the URL for a file, including a secure static page. Returns the URL for a dynamic image map. Returns the URL for a dynamic page. Returns the URL for a static page. Stops session auditing. Retrieves the value of a name/value pair stored in the Session object. See put. 114

136 Chapter 5: HAHTsite Server Object Model Method getadoconnstrbyid getconnectionmanager geterrors gethostname getpagesvisited getservergroupname Description Returns the connection string associated with the ADO connection that has a particular project ID. Returns a reference to the session s DMConnectionManager object. Returns a reference to the session s Errors object. Returns a string containing the hostname of the current machine. This method is useful, for example, to determine which background server is generating an error. Returns a PagesVisited object with the dynamic and secure-static pages visited by this session. Returns a string containing the name of the server group to which the project was published (as set in the project s site description; see the example below). This value can be used to generate a URL, but it s not usually required because most URLs are relative to the application s root directory. Dynamic - server group Server Group Host:moe.haht.com Server Group:webapps File: d:\hahtsite\masters\moe.haht.com\ webapps40.hsg getstatecookiestring getstateid getstring Returns a string that is the cookie for the current session. This string is meaningful if the site is set up to use cookies; see the Application object s isusingcookies method. The string includes the state ID and CGI path and looks something like this: Set-Cookie: HS_StateId=TbI-v6MO- GepKs3M0GYjh-RCNw; path=/cgibin/hsrun/webapps40/examplproj/ Returns the current state ID. Each session has a unique state ID, which is useful for naming temporary files or CORBA objects. Retrieves the value of a variable stored in the Session object using putstring. Also see get. 115

137 Chapter 5: HAHTsite Server Object Model Method Description gettimeout Returns the timeout value for the current session that is, how many seconds must elapse, with the user not accessing the application, before the Application Server will terminate the session. See settimeout, keepalive. geturl getusername isnewapp keepalive lock onstart, onend put putstring remove removesessionlistener returnhahtpageobject Returns the URL for a project item, given a project ID. Returns the user name (if any) associated with the current session. See setusername. Returns true if this is the first dynamic page executed in a new instance of an application. This method returns false for every other dynamic page executed in the application. Resets the timeout value, to keep a session from timing out. See gettimeout, settimeout. Blocks other client threads from modifying data stored in the Session object. Event handlers called when a session is about to start or end. In a Java project, you can customize these methods in HahtSession.java. In a HAHTtalk Basic project, you can override them with the HahtSessionOnStart and HahtSessionOnEnd pseudo-methods. Associates a value with a name and stores the name/value pair in the Session object. See get. Associates a string value with a name and stores the name/value pair in the Session object. See getstring. Removes the association of the named variable with a value. Applies to name/value pairs created with put or putstring. (Java projects only). Removes an event listener from the list of session listeners. (Java projects only). If the requested page has already been instantiated, returns a reference to that object. Otherwise, the method instantiates the page and returns a reference to it. 116

138 Chapter 5: HAHTsite Server Object Model Method settimeout setusername startauditing unlock whoami whocalledme Description Sets the timeout value for the current session, in seconds. See gettimeout, keepalive. Associates a user name with a session. Starts session auditing, beginning with the current page. Disables a lock that has been preventing other client threads from modifying data stored in the Session object. Returns a string containing the name of the currently executing function. Returns a string containing the name of the calling function. The Request object The Request object lets you access data a browser sends to the Web server with an HTTP request, including: Topic Refer to Getting the value of a field Retrieving field values on page 117 Getting the value of a cookie Retrieving cookie values on page 121 Getting information about the Web server and the remote host making the request Retrieving environment variables on page 122 Retrieving field values During a session, the Web browser passes data to the Web server in the form of name/value pairs. One source of such data is a form. On a Web page, forms have many uses for example, collecting data that may be entered into a database, or displaying read-only information. When a user enters information into a form, that information can be sent back to the Web server in one of two ways: 117

139 Chapter 5: HAHTsite Server Object Model If the form s method is GET, the data is sent as part of the URL string, which looks something like this: Name=Scott&Location=SouthPole&Button1=Submit If the form s method is POST, the data is sent to the Web server in a separate message packet. Field variables can come from other sources besides a form. For example, you might design a Web page that passes parameters on a link (using the link s Query field). Or you might place in-line code on a Web page that calculates a value and passes it to the destination page. Each variable is passed as a name/value pair on the URL. The catalog_main.html page from Haht_Intro demonstrates two methods of passing fields to a destination page. First of all, each category (OUTDOOR, HOUSEHOLD, and so on) is actually an image which functions as a link to the destination page. The query string for the link contains the category of item being searched for for example, CatGrp=4 for Outdoor items. In addition, you can enter a product name and click on SEARCH BY NAME, which adds the name/value pair SearchName=youritem to the query string. 118

140 Chapter 5: HAHTsite Server Object Model Retrieving field values Whether the data comes from a form or by some other means, a request typically includes a number of field variables. The Request object s geturlfield method lets you access these values without the need to determine whether the data was sent using GET or POST. Given a field name, geturlfield returns the field s value. Returning to the Haht_Intro example, the destination page, CatalogDisp.html, first tests to see if the query string has a value for CatGrp ; if that value is missing, it tests for a value for SearchName. It uses one of those values to define a shared query over the database. HAHTtalk Basic If arequest.geturlfield("catgrp") <> "" Then... ElseIf arequest.geturlfield("searchname") <> "" Then... sparam = "'%" & arequest.geturlfield("searchname") & "%'"... End If Testing for a field s existence The Haht_Intro example tests for an empty string, which can mean one of two things: either the field cannot be found, or the field actually contains an empty string (""). If you simply want to check whether a field exists, use the geturlfieldexists or geturlfieldcount method. Retrieving a field s value by its index If you call geturlfield with an index into the collection of field variables, it returns the name/value string corresponding to that index. To retrieve the values of all fields in a form, you could use code like this: Java for (int fieldnum=1; fieldnum<=arequest.geturlfieldcount(); fieldnum++) out.print(arequest.geturlfield(fieldnum) + "<BR>"); 119

141 Chapter 5: HAHTsite Server Object Model HAHTtalk Basic Dim FieldNum As Integer For FieldNum = 1 to arequest.geturlfieldcount() Print arequest.geturlfield(fieldnum) & "<BR>" Next FieldNum (Note that indexing into the field array is one-based, not zero-based.) In this case, each field would be returned as a name/value string, like this: txtlastname=simpson txtfirstname=bart txtcity=springfield Button1=Submit If you index past the number of available fields, the method returns an empty string. Fields with multiple values Sometimes a form will have more than one value for the same field. For example, a list box like the one shown below contains multiple values, and the user can select more than one item in the list: In this case, the browser sends a name/value pair, using the same fieldname, for each item selected for example, "txtcity=berlin&txtcity=amsterdam". To retrieve these values, you use the same methods as above, but with an additional argument: geturlfield (fieldname, n) returns the value of the nth occurrence of fieldname. geturlfieldcount (fieldname) returns the number of values the browser sent for a particular field. A count of zero means that the field isn t present in the form data; perhaps the user made no selection. geturlfieldexists (fieldname, n) returns true if occurrence n of field fieldname exists, and false otherwise. 120

142 Chapter 5: HAHTsite Server Object Model Adding fields and overriding field values On the destination page, you can call seturlfield to override the value of a field, and you can call addurlfield to set the value of an additional field, which will then behave as if it had been passed from the calling page. Retrieving cookie values A cookie is a string passed in the HTTP headers between a Web server and a browser. If the browser is configured to accept cookies, it will store the cookies on the user s system and later, on request, will make the cookie available to the Web server. Information stored in cookies can include items such as user names, user preferences, or pages last visited. In HAHTsite, if the site is configured to use cookies, the state ID is also passed in a cookie. The Response object contains methods to set cookies; the Request object, methods to retrieve cookie values. You retrieve cookie values just as you retrieve field values. getcookiecount returns the number of cookies sent from the browser. getcookie(cookie) returns the value of the named cookie. getcookie(index) treats the cookies like an array and returns the cookie corresponding to the index argument; the first cookie has an index of one. Retrieving cookie collections A single cookie may store several pieces of data for example, dimensions=height=10&width=5. These multiple-value cookies are also called cookie collections. To retrieve these values, you must use the getcookie method and then parse the results. For example, Java String mycookie = arequest.getcookie("dimensions"); HAHTtalk Basic Dim MyCookie As String MyCookie = arequest.getcookie("dimensions") would return height=10&width=5. For information on setting these cookie values, see Multiple values within a single cookie on page

143 Chapter 5: HAHTsite Server Object Model Retrieving multiple cookies with the same name A cookie collection (above) refers to a single cookie with multiple values. However, you can also have several cookies with the same name but different paths. In this case, they are all sent with the request string, beginning with the deepest path. For example, the cookie with a path of www/home/products would appear on the string before www/home. If you simply call arequest.getcookie(cookie), you will retrieve the first cookie value on the string. However, you can also index into the set of cookies: getcookiecount(cookie) returns the number of values returned for this cookie. getcookie(cookie, index) returns the cookie value corresponding to index. For more information on cookies, including the path field, see Setting cookies on page 127. Retrieving attachments An HTTP request often includes one or more attachments, which are placed in temporary files in the Application Server s userroot directory. geturlattachmentexists returns true if the named attachment exists, and false otherwise. geturlattachmentcount returns the number of attachments transferred. geturlattachment returns the name of the temporary file associated with the file upload form field. geturlattachmenttype returns the content-type for the attachment associated with the file upload form field. If the browser didn t send a content-type, then the return value is an empty string. For more information about attachments, including an example, see Working with a file attachment on page 142. Retrieving environment variables An HTTP request can include information such as the request method ( GET, POST, and so on) or the content-type or length of the data being transferred. The Web server passes this information to the CGI program in the form of environment variables. Just as the geturlfield method retrieves the value of a form field, the getservervariable method retrieves the value of an environment variable. 122

144 Chapter 5: HAHTsite Server Object Model getservervariablecount returns the total number of environment variables passed to the Web server. getservervariable(variablename) returns the value of an environment variable. (The name is not case sensitive.) getservervariable(index) returns the value of the environment variable corresponding to the given index, in the form name=value. If the name can t be found, or if the index into the collection of environment variables is out of range, the method returns an empty string. Tip - If you are debugging an application, you can view the Web server s environment variables in HAHTsite s Output window. This code prints out all the environment variables returned by the Web server: Java int numvars = arequest.getservervariablecount(); for (int i = 0; i < numvars; i++) { out.print(arequest.getservervariable(i) + "<BR>"); } HAHTtalk Basic Dim NumVars As Integer, FieldNum As Integer NumVars = arequest.getservervariablecount() For FieldNum = 1 to NumVars Print arequest.getservervariable(fieldnum) + "<BR>" Next FieldNum The environment variables returned depend on the Web server you re using and the operating system under which you are running. For more information, consult the documentation for your Web server. Summary of Request object methods This table summarizes the methods of the Request object. For particulars, consult the online help for the Server Object Model. 123

145 Chapter 5: HAHTsite Server Object Model Method addurlfield getcookie getcookiecount getinputstream getservervariable getservervariablecount geturlattachment geturlattachmentcount geturlattachmentexists geturlattachmenttype Description Adds a name/value pair to the set of fields passed from the calling page. You can then retrieve its value with geturlfield. Given the name of a cookie, returns its value. Given an index, treats the cookies like an array and returns the cookie corresponding to the index argument; the first cookie has an index of one. Given a cookie name and an index n, returns the value of the nth occurrence of the cookie. Returns the number of cookies sent from the browser. Given a cookie name, returns the number of cookies with this name. Returns the java.io.bytearrayinputstream object for the client input stream. Given the name of an environment variable, returns its value. (The name is not case sensitive.) Given an index, returns the value of the corresponding environment variable, in the form name=value. If the name cannot be found, or if the index into the collection of environment variables is out of range, the method returns an empty string. Returns the total number of environment variables given by the Web server to the Application Server. Returns the name of the temporary file associated with the file upload form field. Returns the number of attachments transferred. Returns true if the named attachment exists, and false otherwise. Returns the content type of the attachment associated with the file upload form field. 124

146 Chapter 5: HAHTsite Server Object Model Method geturlfield geturlfieldcount geturlfieldexists getuserprop ispost seturlfield setuserprop Description Given a field name, returns the value of a field variable. (The name is case insensitive.) Given an index (one-based) into a set of fields, returns the corresponding name/value pair. If a field cannot be found, the method returns an empty string. Since there are times when an empty string may be a valid field value, this method is not useful for checking for the existence of a particular field. To check for a field s existence, use the geturlfieldexists or geturlfieldcount method. Returns the number of name/value pairs in the form or on the URL.This value refers to the fields the browser sends with the request, not to the total number of fields in a form as it was created. Given a field name, returns the number of values sent for that field. Note that: If a field has multiple values, each value the browser sends counts as a separate field. Only the fields the browser sends are counted. If a list box has 12 possible choices, and the user selects 3, then the count is incremented by 3, not 12. Given a field name, returns true if the specified field exists, and false otherwise. Given a name and index n (one-based), returns true if the nth occurrence of the field exists, and false otherwise. Returns the value of a user-defined property. Returns true if this URL is a POST operation, and false if it is a GET. Overrides the value of a URL field that was passed to this page. If the field doesn t exist, this method has no effect. Sets a user-defined property to a given value. 125

147 Chapter 5: HAHTsite Server Object Model The Response object The Response object lets the Web server send data back to the browser. It includes methods for these purposes: Topic Refer to Writing header data Writing headers on page 126 Setting the values of one or more cookies Writing out the HTML Setting cookies on page 127 Writing the HTML output on page 129 Writing headers Headers are part of the HTTP protocol and include information describing the data being sent, such as the Web server name and version, the content type and length, the date the document was last modified, language and character set information, and redirector information. Each header line ends with a header mark, consisting of the <cr><lf> characters. A blank line signifies the end of the header section. Some actions for example, setting a cookie must take place while the Web server is still emitting the HTTP headers, before it starts to send HTML code. How, then, do you add header lines to an existing page? If you re adding inline code to an HTML page, the IDE distinguishes between code that generates HTTP headers and code that generates HTML. If you call a method such as addheaderline or setcookie, that output is stored in a separate buffer and is sent as part of the HTTP headers. This feature lets you add in-line code to a page without worrying about the mechanics of writing headers versus writing HTML. Terminating headers If you re writing a separate code page instead of in-line code, then you re responsible for writing the headers and calling endheaders appropriately. If you call one dynamic page from another as a direct call, not a link then you must first call endheaders, so that the HTTP headers will not be displayed on the page. To terminate headers, add this line to your in-line code: 126

148 Chapter 5: HAHTsite Server Object Model Java aresponse.endheaders(); HAHTtalk Basic aresponse.endheaders Anything below that line is automatically emitted as part of the HTML output stream. If you don t explicitly call endheaders, it is assumed to have been called at the end of the page. Writing custom headers Normally, the HAHTsite IDE writes a standard Response header. However, you can send a custom header by calling the addheaderline method. If you are not currently in headers, the write operation is suppressed. Adding content information to a header line Once a header line has been written, it can t be changed. The one exception is the content-type header line, containing the MIME type of the data being sent, such as "text/html" or "image/gif." Within the IDE, the default content-type is text/html. To change it, call the setcontenttype method. For more information about HTTP headers, consult a reference such as W3C ( Setting cookies Setting a cookie sends it to the client browser, to be stored (with the user s permission) on the user s system for later retrieval. (See Retrieving cookie values on page 121.) Cookies must be set in the HTTP headers (see Writing headers on page 126). To set a cookie, you specify its name and value. You may also want to set additional attributes, such as the cookie s expiration date or a valid domain and path for returning the cookie. Or you may want to stipulate that the cookie should be sent only over a secure connection. setcookie(cookie, value) sets the cookie using default attributes (see the table, below, for defaults). setcookie(cookie, domain, expires, path, secure, value) sets the additional attributes described in the table. 127

149 Chapter 5: HAHTsite Server Object Model Parameter cookie domain expires path secure value Description The name of the cookie, which should be unique for the given path. (Within different directories or subdirectories, there may be cookies with the same name.) Specifies an Internet domain name, such as haht.com. The cookie is sent only in response to requests to the named domain. Note that domain will match any hosts within that domain; for example, haht.com would also match a hostname of products.haht.com. If domain is null, it defaults to the hostname of the Web server that set the cookie in the first place. Specifies the date on which the cookie expires, in standard GMT format (for example, Mon, 29-Jun-98 18:03:00 GMT ). If expires is null, or if the date isn t later than the current date, the cookie automatically expires when the session ends. Specifies a path within a specified domain. The cookie is sent only in response to requests to this path or any directories contained within it. A path of /docs would also match /docs/techsupport and /docs/marketing. If path is null, then it defaults to the application path. This argument is a boolean; if true, the cookie is secure, meaning that the browser should send the cookie only if it has a secure (HTTPS) connection to the Web server. (The default is false.) A string containing the cookie s value. Multiple values within a single cookie It s possible to set a cookie that contains multiple pieces of data. This is sometimes called a cookie collection. To set these values, call setcookie, passing it the cookie name and a single string that contains all the cookie data, separated by a delimiter that s not used elsewhere in the cookie. Here s an example that uses the ampersand as a delimiter: Java aresponse.setcookie("dimensions", "height=10&width=5"); HAHTtalk Basic aresponse.setcookie "dimensions", "height=10&width=5" 128

150 Chapter 5: HAHTsite Server Object Model To retrieve these values, see Retrieving cookie collections on page 121. For more information about setting cookies, consult the documentation for your Web server. Writing the HTML output Typically, you write HTML output using print or println methods (in Java) or the Print statement (in HAHTtalk Basic). You must add the necessary HTML paragraph formatting tags such as <BR> or <P>...</P>. Java In a Java project, each Page automatically gets the default HTMLWriter, using this code: HtmlWriter out; out = aresponse.getwriter(); If you add in-line code to your page, you can use print or println statements like this: out.print(arequest.geturlfield("name") + "<BR>"); HAHTtalk Basic In a HAHTtalk Basic project, you can simply call the print statement, like this: Print arequest.geturlfield("txtlastname") & "<BR>" The output from write operations is always buffered. At the end of the page, the buffer is flushed. If you re generating a long page, you can call the Response object s flush method to flush the output and begin buffering the data again. Additional write methods There are two additional write methods you may want to use: writebinary writes binary data, such as GIF data. You must set the page s content-type to image/gif (or jpeg or png). setwriter lets you use a subclassed HtmlWriter for example, one that always writes its output to a file. 129

151 Chapter 5: HAHTsite Server Object Model Summary of Response object methods Method addheaderline clear end endheaders flush getcontenttype getoutputstream getwriter Description Outputs a full header line. The Application Server automatically adds the header mark, signifying end-of-line. Empties the Response object s output stream. Flushes the output stream and closes the Response writer. Terminates the header section of the response with a CR/LF sequence. Flushes the output stream and begins buffering data again. Returns a string containing the content-type header line. Returns the current output stream. Returns the current HTML writer. HTMLEncode Processes a string according to the HTML 3.2 specification for special characters, so that they will display correctly on an HTML page. inheaders reset setcontenttype setcookie setoutputstream Returns true if headers are still being output, and false if endheaders has been called. Empties the output stream. Sets the content-type header line to the specified type. You can call setcontenttype multiple times if necessary. When endheaders is called, the Application Server emits the content-type header line using the last value you set. This functionality can be useful if you need to change the content type on the fly. Sets a cookie. Sets the current output stream. 130

152 Chapter 5: HAHTsite Server Object Model Method setwriter URLEncode write writebinary Description Sets the HtmlWriter for the Response object. This method lets you use a subclassed HtmlWriter for example, one that always writes its output to a file. Processes a string according to the RFC 2068 and RFC 1808 specifications for special characters, so that the string can be sent in HTTP headers. Writes a string to the output stream of this Response object. Writes binary data, such as GIF data. 131

153 Chapter 5: HAHTsite Server Object Model 132

154 Forms-Related Programming 6 What s in this chapter Calling a subroutine from a form Writing the subroutine Associating the subroutine with a form Attaching a file to a form Adding a File Upload control to a page Working with a file attachment Custom Form Handler widgets Writing the form-handler function Creating the custom form-handler widget

155 Chapter 6: Forms-Related Programming What s in this chapter In most cases, you handle the submission of a form using a data agent or a page that includes code that parses a URL to get the values submitted in the form. However, HAHTsite provides additional form-handling capabilities. For instance, you can have your application call a HAHTtalk Basic subroutine or a Java method when a form is submitted. One of the examples in this chapter illustrates how you might use such a subroutine to write a Binary Large Object named in a form to a database. Using the File Upload form field, a user can submit a file along with a form. When the form is submitted, the file is moved to the Application Server. The chapter discusses both how to add a File Upload field to a page and how to manage uploaded files. Finally, the chapter explains how to create a custom Form Handler widget in a HAHTtalk Basic project. You may use a custom Form Handler widget if your application requires a form handler that does something other than save form data to a file or a Web page or include that data in an message. Calling a subroutine from a form When you define the properties of a form, you can specify an action that should occur when the form is submitted. Often, this action is to loop back to the form page or to load a dynamic page. However, you can also request that your application call a Java method or a HAHTtalk Basic subroutine when the form is submitted. Why would you want to call a method or subroutine? Usually, you use this feature to perform some task that can t be accomplished with a standard command handler, like the command handler for a Move Next or Insert button. For instance, the example discussed in this section illustrates how you could use a form action of Subroutine to write a Binary Large Object (BLOB) to a database. In this example, the user must enter in a form a name to associate with a picture and the path to an image. 134

156 Chapter 6: Forms-Related Programming The subroutine will then take the following steps: 1 Open a connection to the database, instantiate a Recordset, and set the active connection for the recordset. 2 Get the filename of the image, and open the file for reading. 3 Add a new record to the recordset, and get a handle to the picture field. 4 Read chunks of data from the image file and write them to the database field. 5 Update the recordset. 6 Close the file input stream and the recordset. The listing below shows an abbreviated version of the subroutine as it might appear in a Java project. For a complete listing for the subroutine in both Java and HAHTtalk Basic see Calling a subroutine as a form action on page

157 Chapter 6: Forms-Related Programming Java package FileUploadJava; import com.haht.*; import com.haht.project.*; import com.haht.ado.abstract.*; import java.io.*; class WritePictureToAccess extends Object implements HAHTPage { static final int BUFSIZE = 1024; public void run (Request arequest, Response aresponse) { Connection myconn; try { myconn = Haht.getSession().getConnectionManager(). getsharedconnectionbyname("nameandpict"); } catch (com.haht.hahtexception e) { return; } Recordset myrs = new com.haht.ado.recordset(); myrs.setactiveconnection (myconn); myrs.setcursortype (com.haht.ado.cursortypeenum.adopenkeyset); myrs.setlocktype (com.haht.ado.locktypeenum.adlockoptimistic); try { myrs.open("nameandpict"); } catch (java.lang.exception e) { } 136

158 Chapter 6: Forms-Related Programming Java java.io.file picturefile = new java.io.file (Haht.getApplication().getUserRoot() + '/' + arequest.geturlattachment("uplpicture")); FileInputStream picturestream; Field picturefld; try { picturestream = new FileInputStream (picturefile); } catch (java.io.filenotfoundexception e) { return; } myrs.addnew (); myrs.getfield("name").setstring (arequest.geturlfield("txtname")); picturefld = myrs.getfield("picture"); byte [] picturebuf = new byte[bufsize]; int nbytesread = 0; do { try { nbytesread = picturestream.read(picturebuf); if (nbytesread > 0) { picturefld.appendchunk (picturebuf, nbytesread); } } catch (java.io.ioexception e) { } } while (nbytesread > 0); 137

159 Chapter 6: Forms-Related Programming Java } } myrs.update(); try { picturestream.close(); } catch (java.io.ioexception e) { } myrs.close(); com.haht.io.htmlwriter out = aresponse.getwriter(); out.print("image written to database"); Writing the subroutine Obviously, the content of your subroutine will be determined primarily by what you want the subroutine to do. However, there are a few guidelines that you should follow. In a Java project, your class must implement the HAHTPage interface. This interface requires that you implement one method, run, whose signature is shown below. void run (Request arequest, Response aresponse) If you implement this method, when HAHTsite calls your class s run method, it will pass to the subroutine a Request object that contains the URL used to execute the subroutine. You can parse this URL to obtain information such as the picture name entered on the form that was submitted: arequest.geturlfield("txtname"); HAHTsite also passes to the run method a Response object, which you can use to send HTML to the user s browser. In addition, you have the option of passing both the Request and Resposne objects to a dynamic page when your method has completed its part of the job. In a HAHTtalk Basic project, there are no similar requirements for a Basic subroutine. However, you may need to get references to your session s Request and Response objects for the same reasons you need them in a Java method. You can get these references using the following code: 138

160 Chapter 6: Forms-Related Programming HAHTtalk Basic Dim aresponse As Object Dim arequest As Object Set aresponse = Haht.getResponse() Set arequest = Haht.getRequest() Associating the subroutine with a form Once you ve written your subroutine, you can associate it with a form so that when the form is submitted, the subroutine will be executed. To create this association, perform the following steps. To specify that a subroutine should be called when a form is submitted 1 Right-click the form to bring up a pop-up menu that displays the operations you can perform in this context. 2 Select Form... from the pop-up menu. The Form Properties dialog appears. 3 From the Type list box, select Subroutine. 4 In the Path text box, enter the name of the method or subroutine. In a Java project, you may have to fully qualify this method name: If the method is implemented outside the page that contains the form that is, defined in a Java source file this name must have the form packagename.classname.methodname. For example, FileUploadJava.WritePictureToAccess.run would be a valid name, 139

161 Chapter 6: Forms-Related Programming assuming that the WritePictureToAccess class is part of the project FileUploadJava. (Remember that for Java projects, the project name is the default package name.) If the method is implemented on the page that contains the form in the Server-side Code view you need only supply the method name. In a HAHTtalk Basic project, you simply enter the name of the subroutine. 5 Click OK. Your form will now cause a subroutine to be called when the form is submitted. Attaching a file to a form HAHTsite s File Upload form field enables a user to attach a file to a form and to send the file to the Application Server s initial working directory when the user submits the form. The File Upload form field places a text box and a Browse button onto a form. In his or her browser, the user can either type the name or pathname of a file into the text box or use the Browse button to find the file on his or her local machine or LAN. Note - Not all browsers support this file-upload feature. Netscape Navigator 2.0 and later does support the feature; Internet Explorer 3.0 and earlier does not. When the user submits a form that contains a File Upload field, the name/value pairs for the form s fields are sent to the Web server. The Web server then passes this information to the Application Server, which moves a copy of the file to its initial working directory. By default, the initial working directory is HAHTsiteInstallDir\userroot\projectName for example, C:\HAHTsite4.0\userroot\FileUploadJava. When the file is moved to the initial working directory, it is given a unique name created by prepending the user s state ID (a unique string) to the file s name. You can obtain the unique filename by using a Request object s geturlattachment method. This and other methods related to handling file attachments are discussed in Working with a file attachment on page

162 Chapter 6: Forms-Related Programming Adding a File Upload control to a page You add a file-upload form field to a form using the IDE. The procedure for adding this field is explained below. To add a File Upload field to a form 1 Position your cursor on the page at the point at which you want to place the File Upload form field. If your cursor is inside a form, the File Upload field will be added to that form; otherwise, the IDE will automatically create a form into which to place the new field. 2 From the Insert menu, select Form Field > File Upload, or click the File Upload button. The File Upload form field is written to your form. 3 Right-click the new field to display a pop-up menu of actions you can take in this context. 4 Select Form Field... from the pop-up menu. The Form Field Properties dialog appears. 5 Edit the properties shown on the General tab (optional). The table below explains what information you can enter on this tab. Field Name Explanation The name of the File Upload field. This is the name you use to refer to the Java object that represents the field. 141

163 Chapter 6: Forms-Related Programming Field Value Label Label Alignment Explanation The value of the file-upload field when the form is submitted. Normally, this will be a pathname that the user types in or selects using the Browse button. However, you can provide the field a default value by setting this form-field property. A label that you want to appear to the left or right of the File Upload field when the page is browsed. If you specified a label for the field, choosing the Left radio button causes the label to appear to the left of the field when the page is browsed, and the Right radio button causes the label to be displayed on the right. 6 Click OK. This is all you have to do to enable the user to submit a file with a form and have that file copied to the Application Server s initial working directory. If you want to process the file, you must use the Server Object Model methods discussed in Working with a file attachment below. Working with a file attachment When a file is submitted with a form and you want to handle the file programatically, you can place the code that will process the file in one of two places: In a subroutine to be called when the form containing the file-upload field is submitted. For information on calling a subroutine from a form, see Calling a subroutine from a form on page 134. In user code that is called when a particular form button is clicked, causing the form to be submitted. For information on calling user code from a form button, see Calling user code from a button on page 183. The example used in Calling a subroutine from a form on page 134 is a good illustration of manipulating a file using a subroutine called when a form is submitted. This section refers to that example in explaining how to work with a file submitted with a form. If you recall, the subroutine discussed in that section takes an image file submitted with a form and writes it to a database. In the course of moving the contents of the file to the database, the subroutine performs two actions that you ll always want to perform when working with a file submitted with a form: 142

164 Chapter 6: Forms-Related Programming 1 Check the URL used to call the subroutine to see if the URL contains a field that holds the name of a file attachment. If this field does not exist, the user didn t supply a filename or some error occurred, and you should call an error-message page. You can determine whether the URL contains such a field using the Request object s geturlattachmentexists method as shown below. Java // Check to see if the user has submitted a picture name and a // filename. if (arequest.geturlfieldexists("txtname") && arequest.geturlattachmentexists("uplpicture")) { // Bulk of the subroutine goes here.... } else { // Instantiate an error page and call its run routine.... } HAHTtalk Basic ' Check to see if the user has submitted a picture name and a ' filename. ' If (arequest.geturlfieldexists("txtname") And _ arequest.geturlattachmentexists("uplpicture")) Then ' Bulk of the subroutine goes here.... Else ' Instantiate an error page and call its run routine.... End If 2 Get the name of the file that was transferred to the Application Server. The file won t have the same name it had when the user entered its name in your form. HAHTsite prepends the user s state ID to the original filename 143

165 Chapter 6: Forms-Related Programming so that it turns out looking something like this: T7UqieNDj0YplcN40CEVbC0_Kohahtsite.jpg. You obtain this filename using the Request object s geturlattachment method as shown below. In this example, uplpicture is the name of the form s File Upload form field. Java java.io.file picturefile = new java.io.file (Haht.getApplication().getUserRoot() + '/' + arequest.geturlattachment("uplpicture")); HAHTtalk Basic Dim spicturefilename as String spicturefilename = HahtApplication.getUserRoot() & "/" _ & arequest.geturlattachment("uplpicture") The Request object also provides methods that enable you to determine the content type of an attachment and to determine how many file-attachment fields are in a URL (if there is more than one). The table below summarizes the Request methods related to handling file attachments. Method geturlattachmentcount geturlattachmentexists geturlattachment geturlattachmenttype Explanation indicates how many files were submitted with the form indicates whether the URL contains a file-attachment field for a particular file-upload field gets the name of the file that was attached to the form using a particular file-upload field gets the content type of an attached file. This content type might be something like image/jpeg or audio/basic. 144

166 Custom Form Handler widgets Chapter 6: Forms-Related Programming HAHTtalk Basic projects include a Form Handler widget that enables you to add to a form a button whose action is to write the values of a form s fields to: a file an HTML page an message HAHTtalk Basic projects also give you the ability to create custom form-handler widgets by writing the Basic function that will be executed when the form button representing the widget is clicked. Because this function is passed information about the Web application, information about the environment in which the application is running, and the contents of the form s fields, custom form handlers usually make use of this information. An example form-handler function on page 149 illustrates how to write a function that uses this information in a simple way. Note - The custom form-handler widget is a useful feature, but it has been retained primarily for compatibility with HAHTsite 3.x. This feature has not been ported to Java projects because you can create the equivalent of a custom form-handler widget in Java projects by writing a method that is called when a form is submitted or when a particular form button is clicked. This method can obtain information about the values of form fields and the values of Web-server environment variables using the getservervariable method of the Request class. HAHTsite Basic programmers can also use this technique. The remainder of this chapter is for programmers who want to create new custom form-handler widgets. It explains how to: write a form-handler function in HAHTtalk Basic how to create a form-handler widget based on the Basic function you created earlier Writing the form-handler function The HAHTtalk Basic code around which you build a custom form-handler widget must be a function, not a subroutine. In addition, the name of your function must be the same as the name of the code file that contains it. Included in the HAHTsiteInstallDir\scripts directory is a sample form-handler function FormHand, which is contained in the file FormHand.hbs. You can use this function as a template for your own form handler. 145

167 Chapter 6: Forms-Related Programming Notice that the sample form-handler function requires two parameters, one of type Environment and one of type FormArray. The Environment data structure contains the values of a number of Web-server environment variables and Web-application properties. The FormArray data structure contains the names and values of your form s form fields. For definitions of these structures, see Parameters of the form-handler function on page 146. Parameters of the form-handler function The first parameter required by a form-handler function is a parameter of type Environment. The definition of this data type is shown below. 146

168 Chapter 6: Forms-Related Programming HAHTtalk Basic Type Environment ComputerName as string ComSpec as string GATEWAY_INTERFACE as string HTTP_ACCEPT as string HTTP_CONNECTION as string HTTP_HOST as string HTTP_REFERER as string HTTP_USER_AGENT as string OS as string Os2LibPath as string Path as string PATH_INFO as string PROCESSOR_ARCHITECTURE as string PROCESSOR_IDENTIFIER as string PROCESSOR_LEVEL as string PROCESSOR_REVISION as string QUERY_STRING as string REMOTE_ADDR as string REMOTE_HOST as string REQUEST_METHOD as string SCRIPT_NAME as string SERVER_NAME as string SERVER_PORT as string SERVER_PROTOCOL as string SERVER_SOFTWARE as string SERVER_URL as string SystemRoot as string SystemDrive as string windir as string NewApp as boolean DirName as string HTXName as string PathName as string PageName as string ServerName as string StateId as string Timeout as long End Type 147

169 Chapter 6: Forms-Related Programming The table below shows how the members of this structure map to WebApp properties and environment variables retrievable via the WebApp method Environ$. (For documentation of the WebApp object, see the HAHTsite 3.x programmer s guide. For information about how WebApp properties and methods map to elements in the Server Object Model, see Appendix A, HAHTsite 3.x WebApp Methods and Properties. ) Structure Member ComputerName ComSpec GATEWAY_INTERFACE HTTP_ACCEPT HTTP_CONNECTION HTTP_HOST HTTP_REFERER HTTP_USER_AGENT OS Os2LibPath Path PATH_INFO PROCESSOR_ARCHITECTURE PROCESSOR_IDENTIFIER PROCESSOR_LEVEL PROCESSOR_REVISION QUERY_STRING REMOTE_ADDR REMOTE_HOST REQUEST_METHOD SCRIPT_NAME SERVER_NAME Definition Webapp.Environ$("COMPUTERNAME") Webapp.Environ$("ComSpec") Webapp.Environ$("GATEWAY_INTERFACE") Webapp.Environ$("HTTP_ACCEPT") Webapp.Environ$("HTTP_CONNECTION") Webapp.Environ$("HTTP_HOST") Webapp.Environ$("HTTP_REFERER") Webapp.Environ$("HTTP_USER_AGENT") Webapp.Environ$("OS") Webapp.Environ$("Os2LibPath") Webapp.Environ$("Path") Webapp.Environ$("PATH_INFO") Webapp.Environ$("PROCESSOR_ARCHITECTURE") Webapp.Environ$("PROCESSOR_IDENTIFIER") Webapp.Environ$("PROCESSOR_LEVEL") Webapp.Environ$("PROCESSOR_REVISION") Webapp.Environ$("QUERY_STRING") Webapp.Environ$("REMOTE_ADDR") Webapp.Environ$("REMOTE_HOST") Webapp.Environ$("REQUEST_METHOD") Webapp.Environ$("SCRIPT_NAME") Webapp.Environ$("SERVER_NAME") 148

170 Chapter 6: Forms-Related Programming Structure Member SERVER_PORT SERVER_PORT SERVER_SOFTWARE SERVER_URL SystemRoot SystemDrive windir NewApp DirName HTXName PathName ServerName StateId Timeout Definition Webapp.Environ$("SERVER_PORT") Webapp.Environ$("SERVER_PORT") Webapp.Environ$("SERVER_SOFTWARE") Webapp.Environ$("SERVER_URL") Webapp.Environ$("SystemRoot") Webapp.Environ$("SystemDrive") Webapp.Environ$("windir") Webapp.NewApp Webapp.DirName Webapp.HTXName Webapp.PathName Webapp.ServerName Webapp.StateId Webapp.Timeout The definition of the FormArray structure is shown below: Type FormArray FieldName as string Value as string End Type You must place the definitions of both the Environment type and the FormArray type above your function definition in your code file. For an example function definition, see An example form-handler function. An example form-handler function Assume that your application contains a form that requires a user to submit an address, a user name, and a password. 149

171 Chapter 6: Forms-Related Programming When the user submits this form, the custom form handler: Writes a file, Users.txt, to the Application Server s userroot directory. This file contains the data submitted with the form in a comma-separated format. Sends an message to the user who submits the form. (Note that the code that writes this message uses a member of the Environment structure.) After the custom form handler performs these actions, the application displays a response page that thanks the user for registering and shows the time of registration. The HAHTtalk Basic function for the custom form handler is shown below: 150

172 Chapter 6: Forms-Related Programming HAHTtalk Basic ' Definitions of Environment and FormArray Types go here. Public Function Sample(myEnv As Environment, myfields() As _ FormArray) As Integer On Error Goto Sample_Error Dim i As Integer Dim m As New Message Dim user As String Dim As String Dim password As String For i = LBound(myFields) To UBound(myFields) If myfields(i).fieldname = "Username" Then user = myfields(i).value ElseIf myfields(i).fieldname = "Password" Then password = myfields(i).value ElseIf myfields(i).fieldname = "Address" Then = myfields(i).value End If Next i ' Write information to user's file in UserRoot Open "Users.txt" For Append As #1 Print #1, user & "," & password & "," & Close #1 ' Mail Confirmation m.to.new m.from = "[email protected]" m.subject = "Registration Confirmation" m.smtpserver = "mailhost" m.body.writeln "Registration Confirmation for " & & _ "received from remote host: " & myenv.remote_host m.body.writeln "Your username is: " & user m.body.writeln "Your password is: " & password m.submit 151

173 Chapter 6: Forms-Related Programming HAHTtalk Basic Sample_Error: Sample = 0 ' Go To Response Page Call HS_Response() End Function Creating the custom form-handler widget Once you ve written the HAHTtalk Basic function that performs the actions you want your custom form-handler widget to perform, you can create the widget by following the directions below. To create a custom widget 1 Place your cursor in your form at the position where you want the widget (represented as a form button) to appear. 2 Drag a Form Handler widget from the Widgets folder in your Project window to your page. The Form Handler Properties dialog appears. 3 Click the Custom button in the Form Handler Properties dialog box. The Custom dialog appears. 152

174 Chapter 6: Forms-Related Programming 4 Fill out the Custom dialog box. The table below discusses each form field in the dialog. Form Field Description Code Page Name Redisplay Page Default Button Label Explanation Enter a short name for your custom form-handler widget. HAHTsite adds this name to the list of form handlers you can add to a page (within this project) using the Form Handler widget. Specify the name of the.hbs file that includes your HAHTtalk Basic function. If you leave this box checked, the page that contains your custom form handler will be redisplayed after the form-handler function is executed. If your function calls a dynamic page as the example function does you should remove the check from this box. Supply a label for the form-handler button. 153

175 Chapter 6: Forms-Related Programming 154

176 Form Fields Programming 7 What s in this chapter Setting form-field properties Examples of setting form-field properties Setting and getting form-field properties FormField properties Button properties Checkbox properties Combo properties FileUpload properties ListElement and Listbox classes Radiobutton properties StaticText properties TextArea properties Textbox properties Calculating form-field values Calling user code from a button Code associated with a button versus code associated with a form Configuring a button to call user code

177 Chapter 7: Form Fields Programming What s in this chapter This chapter discusses both how to write code that affects form fields and how to use a form field (a button) to call user-written code. As you ll read below, all HAHTsite form fields (text boxes etc.) are Java objects, and these objects have methods that enable you to set their properties at runtime. While you usually set form-field properties when you design your form using the IDE, you may want to set some properties conditionally. For instance, you may want to make a Move First button invisible if your application is already displaying the first record in a recordset. Another type of form-field programming involves manipulating values retrieved from a data source before they are displayed in form fields. You can change these values by adding code to a page between the data agent that retrieves the values and the form that is populated by the data agent. Finally, the chapter discusses how you can call user code when a particular button (form field) is used to submit the form. Setting form-field properties Each form field in a form whether it be a text box or a radio button is a Java object and has a set of properties (member variables) that you can set. This section begins with a couple of examples that illustrate problems you can solve by setting these form-field properties programatically. The section then presents reference information about what properties you can set for each object and how to set and read the values of these properties. To see the introductory examples, look at Examples of setting form-field properties on page 156. For reference information about form-field properties and how to set them, see Setting and getting form-field properties on page 161. Examples of setting form-field properties This section demonstrates how to solve two common problems by setting form-field properties. The first example assumes that your application uses a form to present the user with information from a database, and that the user can navigate from record to record using Move First, Move Next, Move Previous, and Move Last buttons. The example makes the Move Previous button invisible if the user tries to access a record before the first record and 156

178 Chapter 7: Form Fields Programming makes the Move Next button invisible if the user tries to access a record beyond the last record. The second example illustrates a simple method of internationalizing the static text in a form. Example 1: Turning off visibility for a button Say that you have an application that enables users to work with the records in an employee-information database. Users can view, insert, update, or delete records. They can also navigate the database using Move First, Move Next, Move Previous, and Move Last buttons. Further, assume that you want the Move Previous button to be removed from the form when the user s record pointer is pointing at BOF and the Move Next button to be removed when the user s record pointer is pointing at EOF. 157

179 Chapter 7: Form Fields Programming The code required to implement this feature is very simple. Just place the following code somewhere between the data agent that is populating these fields and the form. Java btnmovenext.setvisible(true); btnmoveprevious.setvisible(true); if (dapopulater.getrecordset().geteof()) { btnmovenext.setvisible(false); } if (dapopulater.getrecordset().getbof()) { btnmoveprevious.setvisible(false); } HAHTtalk Basic btnmovenext.setvisible True btnmoveprevious.setvisible True If (dapopulater.getrecordset().geteof()) Then btnmovenext.setvisible False End If If (dapopulater.getrecordset().getbof()) Then btnmoveprevious.setvisible False End If 158

180 Chapter 7: Form Fields Programming The getbof and geteof methods check to see whether the current recordset of the page s data agent (dapopulater) is pointing before the first record or after the last record. (For more information about HAHTsite s interface to data agents and their recordsets, see Chapter 8, Data-Agent Programming. ) If one of these conditions is true, the appropriate button s setvisible method turns the visibility of the object off. Note - The first two statements in this block make both buttons visible. Without these statements, once a button s visibility was turned off, it would never be turned on again. Example 2: Internationalizing a form Here s another situation in which you might want to set the properties of form fields. Say that you re working with the interface shown in Example 1: Turning off visibility for a button on page 157 and that you want to be able to display the labels next to the text boxes in either English or Spanish. (You can use the same technique to change the language of the text associated with any form field.) First, you might prompt the user for a language preference and store that preference in a session-scope variable, for instance, language. You ll also need to make sure that the labels are Static Text objects, not just text. You can then call the code shown below: 159

181 Chapter 7: Form Fields Programming Java This code assumes that you have defined the variable language in the HahtSession class. This class is defined in the file HahtSession.java, which is located in your project s Session folder. if (hahtsession.language == "Spanish") { stalastname.setvalue("apellido:"); stafirstname.setvalue("nombre:"); stastreetaddr.setvalue("direccion:"); stacity.setvalue("ciudad:"); stastate.setvalue("estado:"); stazipcode.setvalue("codigo Postal:"); } HAHTtalk Basic This code assumes that you ve defined the global variable language in the file globals.hbs. If (language = "Spanish") Then stalastname.setvalue "Apellido:" stafirstname.setvalue "Nombre:" stastreetaddr.setvalue "Direccion:" stacity.setvalue "Ciudad:" stastate.setvalue "Estado:" stazipcode.setvalue "Codigo Postal:" End If This code uses the setvalue method of the Static Text object to change each object s Value member variable. Note - To change a Static Text object s label as opposed to the text itself you can use the setlabel method. (In the example above, the Static Text objects don t have labels because the objects are being used as labels.) You can also use the setlabel method to change the label associated with other form fields, for example, text boxes and radio buttons. For most fields, the label you supply appears to the left or right of the field when the page is browsed. 160

182 Chapter 7: Form Fields Programming Setting and getting form-field properties This section contains primarily reference material that details what properties you can set for each form-field object and what methods you call to set these properties. However, there are a couple of things you should understand about HAHTsite form fields and their properties before you begin setting these properties. First, as was mentioned earlier, each form field is a Java object. Therefore, it s important to understand the relationships between the Java classes from which these objects are created. These class relationships are shown in the figure below. FormField Buttons Checkbox FileUpload Listbox Radiobutton StaticText TextArea Textbox ListElement Combo As you can see, most of the classes that represent objects you can place on a page (like Button and Checkbox) are subclasses of FormField. This means that all the properties and property-accessor methods defined in the FormField class are inherited by the other classes shown. (For the purposes of this documentation, this hierarchy means that the reference information for an object of type Textbox is the union of the information presented for the FormField class and that presented for the Textbox class.) Combo is a subclass of Listbox as well, but this relationship doesn t affect your use of these two classes because they expose the same interface. One other word of introduction. There are two methods of setting form-field properties in HAHTsite: you can either use a set method or set a member variable directly. The code below illustrates the use of a set method. 161

183 Chapter 7: Form Fields Programming Java stalastname.setvalue("apellido:"); HAHTtalk Basic stalastname.setvalue "Apellido:" The following code illustrates how you can set a member variable of an object directly: Java stalastname.value = "Apellido:"; HAHTtalk Basic stalastname.value = "Apellido:" HAHT recommends that you use the set methods to set form-field properties, and, consequently, the upcoming sections document these methods as the interface to use in setting and reading form-field properties. Again, though, the member variables that represent these properties are public and can be set directly. For a list of the member variables you can set for a particular object, see the online help for the HAHTsite Server Object Model. The table below directs you to information about setting the properties of the object in which you re interested. Section FormField properties on page 163 Button properties on page 165 Description explains how to set and read the properties that are common to all form fields. FormField is a superclass of all the other classes listed in this table; therefore, the methods listed here can be used with any form-field object. explains how to set and read the properties of a button (a Submit button, a Reset button, etc.) 162

184 Chapter 7: Form Fields Programming Section Checkbox properties on page 167 Combo properties on page 168 FileUpload properties on page 168 ListElement and Listbox classes on page 169 Radiobutton properties on page 175 StaticText properties on page 176 TextArea properties on page 178 Textbox properties on page 178 Description explains how to set and read the properties of a check box explains how to set and read the properties of a combo box explains how to set and read the properties of a file-upload widget, which enables you to copy a file to the Application Server when you submit your form explains how to change the contents of a list box at runtime explains how to set and read the properties of a radio button explains how to set and read the properties of a static-text object explains how to set and read the properties of a text-area widget explains how to set and read the properties of a text box FormField properties As was mentioned earlier, FormField is a superclass of the classes representing the following form-field objects: Button Check box Combo box File-upload control List box Radio button Static text Text area Text box 163

185 Chapter 7: Form Fields Programming Because these objects are created from subclasses of the FormField class, you can use FormField methods to set properties that all of the objects have in common. For example, you can set the visibility of any object like this: Java This code changes the Visible attribute of a Button object from on to off. It assumes that the object btnmovefirst has already been instantiated. btnmovefirst.setvisible(false); HAHTtalk Basic This code changes the Visible attribute of a Button object from on to off. It assumes that the object btnmovefirst has already been instantiated. btnmovefirst.setvisible False The following table lists the most commonly used set and get methods for use with all the subclasses of FormField. Method addextattr setlabelalignment setlabel setname Explanation enables you to add an extended attribute to a form-field object. This extended attribute is an HTML attribute not represented by one of the object s standard properties (value, etc.). Note that case matters when you re storing and retrieving these extended attributes determines whether a form field s label is displayed on the left or right of the field when the page is browsed. See setlabel. establishes the value of a label to be displayed to the left or right of the form field when the page is browsed. All form-field objects except those of type Button can display labels. changes the name of the form field. You use this name to refer to the object that represents the form field. 164

186 Chapter 7: Form Fields Programming Method setvalue setvisible getextattrvalue getlabelalignment getlabel getname getvalue isvisible tostring Explanation establishes the value of the form field. This is the value that is submitted with the form. In some cases, the value is also displayed in the browser. For example, the value of a button is used as its label, and a text box s value appears in the text box. determines whether a field is visible or not. That is, a page s run method or HS_ subroutine does not generate HTML for an invisible form field. retrieves an extended attribute of an object by name. The name you use to retrieve the value of an attribute is case sensitive. indicates whether the object s label is to be displayed on the left or right of the corresponding form field retrieves a form field s current label retrieves a form field s current name retrieves a form field s current value indicates whether a form field is currently marked as visible or not returns an HTML representation of the form field as a string Button properties HAHTsite enables you to put four types of buttons on a page: Submit button - submits the values on a form to a form handler or performs some database-related action Reset button - returns the form fields values to what they were when the page was first displayed Button button - executes a client-side script Image button - similar to a Submit button except that its label is an image instead of text You can set a button s properties programatically to accomplish such tasks as the following. Suppose that you want to set a session-scope variable to change the labels on all of your buttons from text labels to pictures. You could accomplish this task using code similar to the following: 165

187 Chapter 7: Form Fields Programming Java if (hahtsession.picturesonbuttons == true) { btnmovefirst.setstyle (com.haht.project.form.button.style_image); btnmovefirst.setpictureurl(haht.getsession().createstaticurl ("HAHTsite.gif","default")); } HAHTtalk Basic If (HahtSession.picturesOnButtons = True) Then Set Haht_TempJavaObj = GetJavaClass _ ("com.haht.project.form.button") btnmovefirst.setstyle Haht_TempJavaObj.STYLE_IMAGE btnmovefirst.setpictureurl HahtSession.createStaticURL _ ("HAHTsite.gif", "default") Set Haht_TempJavaObj = Nothing End If You use the setstyle method to change a button from one type to another (from a Submit button to an Image button, for example) and the setpictureurl method to specify the location of the image to be displayed on the button. The table below lists the methods of the Button class that you can use to set and retrieve the properties of a Button object. Method setlowsrcurl setpictureurl setstyle getlowsrcurl getpictureurl Explanation specifies the URL of the image to be used as an Image button s Low-Resolution Image specifies the URL of the image to be used as an Image button s Source Picture sets a button s type to one of the following values: Submit, Reset, Button, or Image gets the URL of the image being used as an Image button s Low-Resolution Image gets the URL of the image being used as an Image button s Source Picture 166

188 Chapter 7: Form Fields Programming Method getstyle Explanation gets the type of a button Checkbox properties When you add a check box to a form using the IDE, you can specify: the value of the check box if the form it is on is submitted while the box is checked the value of the check box if the form it is on is submitted while the box is unchecked the initial state of the checkbox: checked or unchecked You can also set or read these properties and others at runtime using methods of the Checkbox class. For example, you might want to determine at runtime whether a check box, chkexample, should be checked or unchecked when it is first displayed. To do this, you would include code similar to the following above the form that contains the check box. Java if (...) { chkexample.setchecked(true); } HAHTtalk Basic If (...) Then chkexample.setchecked True End If The table below enumerates the methods used most often to work with check box properties. Method setchecked Explanation enables you to change the checked status of a check box from unchecked to checked or from checked to unchecked 167

189 Chapter 7: Form Fields Programming Method setcheckedifvalueis setuncheckedvalue getuncheckedvalue ischecked Explanation sets the checked status of a check box to checked if a string that you pass as an argument matches the current checked value of the check box sets the value the check box has when the check box is unchecked retrieves the check box s unchecked value returns the value of the Checked member variable, which indicates whether the check box will be checked when the page it is on is displayed Note - You set the checked value of a check box using the setvalue method, which Checkbox inherits from FormField. Combo properties In the Server Object Model, Combo is a subclass of Listbox. However, while Combo overrides a few methods defined in the Listbox class, this is entirely transparent to you. The interface used to set and read combo box properties is exactly the same as the interface used to work with list boxes. See ListElement and Listbox classes on page 169 for a description of this interface. FileUpload properties The properties you can set for a file-upload field are all very general. You can set the field s: Name Value Label Label alignment Visibility The methods you use to work with these properties are all inherited from FormField. Therefore, you can find reference information about these methods in FormField properties on page

190 Chapter 7: Form Fields Programming ListElement and Listbox classes The ListElement and Listbox classes enable you (and HAHTsite) to create list boxes that contain particular sets of list entries, or elements. An object of the Listbox class represents the list box itself, and each entry in the list is an object of type ListElement. List box List element Note - List elements can also be added to combo boxes since Combo is a subclass of Listbox. There are three possible types of list elements: Design-time list elements. HAHTsite creates design-time list elements when you use the IDE to create a list box and add list items to the list. For each list item, HAHTsite instantiates a list element with a type property whose value is STATIC_ELEMENT. Populater list elements. If you design a page so that a data agent is used to populate a list box or combo box, for each list item, HAHTsite instantiates a list element of type POPULATER_ELEMENT. Runtime list elements. These are elements of type PAGE_RUN_ELEMENT that you add to a list box or combo box by making calls to ListElement and Listbox methods. Any list box can contain any combination of these three types of elements. For information about creating list elements and working with list boxes, see the following sections: Creating list elements on page 169 Getting and setting ListElement properties on page 171 Adding list elements to a list on page 171 Selecting an element in a list on page 172 Finding an item in a list on page 173 Getting and setting Listbox properties on page 173 Creating list elements A list element has four member variables: A display value. This is the string that is displayed in the list. 169

191 Chapter 7: Form Fields Programming An internal value. This is the value of the list box when the form containing the list box is submitted with a particular display value selected. Each display value has a corresponding internal value. A selected status. If a list element's selected status is set to true, the list element will be highlighted when the list box is displayed. An element type (or creation type). This type indicates whether the element was created at design time, by a populater, or by user-written code. The following constants represent these three types: STATIC_ELEMENT, POPULATER_ELEMENT, and PAGE_RUN_ELEMENT. HAHTsite uses this type to determine when to remove elements from a list. Design-time elements are never removed; populater elements are removed each time the list box is populated; and page-run elements are removed each time the page is run. To create a list element, you call one of the ListElement class's constructors. ListElement(String adisplayval) ListElement(String adisplayval, String aninternalval, boolean aselonoff, int acreateflag) If you use the first form of the constructor, HAHTsite sets the list element's internal value to the empty string, its selection flag to false, and its type to STATIC_ELEMENT. The code fragments below illustrate how to instantiate a list element in both Java and HAHTtalk Basic. Java ListElement element1 = new ListElement("JaneDoe", "12345", false, PAGE_RUN_ELEMENT); HAHTtalk Basic Dim element1 As Object Set element1 = CreateJavaObject("ListElement", "Jane Doe", _ "12345", False, PAGE_RUN_ELEMENT) In this case, the list element s display value is Jane Doe, its internal value is Jane s employee number 12345, and the element will not be highlighted by default. 170

192 Chapter 7: Form Fields Programming Note - It's also possible to create a list element and insert that element into a list in a single step. For information on how to do this, see Adding list elements to a list on page 171. Getting and setting ListElement properties Once you've created a ListElement, you can read or set the properties of this object using the methods listed in the table below. Method setcreateflag setdisplayvalue setinternalvalue setselected getcreateflag getdisplayvalue getinternalvalue isselected Description Indicates whether this list element was created at design time, by a populater (a data agent), or by user code. In your code, you ll want to set this flag to PAGE_RUN_ELEMENT to indicate that you re adding this item to the list at runtime. Sets a list element s display value, the value that will be shown in the list box. Sets a list element s internal value. This value will be the list box s value when the form is submitted. Sets the list element s selected flag, to determine whether the list element will be highlighted when the list box is displayed. Reads the list element s element type: STATIC_ELEMENT, PAGE_RUN_ELEMENT, or POPULATER_ELEMENT. Reads the list element s display value. Reads the list element s internal value. Gets the value of the list element s selected flag. Adding list elements to a list This section covers how to insert list elements into a list box and how to remove them. You have three options when you insert a list element (or elements) into a list box. You can: Insert a list element that you created earlier. Create a list element and insert it into a list box in a single step. Insert a vector of list elements into a list box. 171

193 Chapter 7: Form Fields Programming The prototypes for the methods that perform these tasks are shown below: int insertelementat(listelement anelement, int index) int insertelementat(string adisplayval, String an InternalVal, boolean aselonoff, int acreateflag, int index) void insertelementat(vector alist, int index) For each method, the index parameter indicates the point in the list at which the new element(s) should be added. For example, if you specify an index of 3, the new element will become the third item in the list box's list. Note - You can replace an existing list item using the method setelementat. (This method s counterpart, getelementat, returns the ListElement object at a particular index.) To remove an item from a list box, use one of the methods shown in the table below. Method removeallelements removeelementat removeelements Description Removes all of a list box s list items. Removes the list item at a particular index into the list. Removes all list items of a particular type: STATIC_ELEMENT, PAGE_RUN_ELEMENT, or POPULATER_ELEMENT. Selecting an element in a list Using methods of the Listbox class, you can specify: Whether the user can select only one value from the list box before submitting the form containing the list box, or whether the user can select several values. Which list element or elements (if any) should be highlighted (selected) when the list box is first displayed. A Listbox object contains a member variable that determines whether multiple selections are allowed. You can read the value of this variable using the method ismultiple, and you can set the value using the method setmultiple. If the variable is set to true, multiple selections are allowed. Note - One difference between list boxes and combo boxes is that combo boxes do not allow multiple selections. To indicate that a list item should be selected or deselected when the list box is displayed, use one of the methods listed in the table below. 172

194 Chapter 7: Form Fields Programming Method selectifdisplayvalueis selectifinternalvalueis selectitem deselectall deselectitem Description Clears the existing selection, and then selects all of the items in the list whose display value matches a value you supply. Clears the existing selection, and then selects all of the items in the list whose internal value matches a value you supply. Selects the item at the position you indicate. If this is a single-select list box, all other items are deselected. Deselects all of the elements in the list. Deselects the element at the position indicated by an index. Finding an item in a list The Listbox class contains several methods that enable you to determine the current location (index) of a list element within a list box. These methods are shown in the table below. Method finddisplayvalue findinternalvalue getselected Description Finds an element with a display value equal to a value you supply. The comparison ignores case. Finds an element with an internal value equal to a value you supply. The comparison ignores case. Finds the first selected item that follows an index you provide. Getting and setting Listbox properties The Listbox class also contains accessor methods that enable you to get or set a number of properties of the list box or of a list element contained in the list box. See the table below. 173

195 Chapter 7: Form Fields Programming Method setinsertpopulaterelementsfirst setmultiple setsize getdisplayvalue getelementcount getinsertpopulaterelementsfirst getinternalvalue ismultiple isselected getsize Description Moves any list elements of type POPULATER_ELEMENT to the beginning of the list. By default, such entries are placed at the end of the list. Sets or clears the HTML attribute multiple for this list box. This attribute controls whether or not multiple selections are allowed in the list box. Sets the HTML size attribute. The size attribute controls the number of elements that will be visible when the list box is displayed in the browser. Returns the display value of the list element at the index you supply. Returns the number of list elements in the list. Indicates whether list elements of type POPULATER_ELEMENT will be displayed in the list box first or last. Returns the internal value of the list element at the index you supply. Returns true if the multiple attribute is set for this list box; otherwise, it returns false. Returns true if the list element at the index you specify is selected. Returns false if the item is not selected or doesn't exist. Returns the value of the list box s size (HTML) attribute. The size attribute controls the number of elements that will be visible when the list box is displayed in the browser. 174

196 Chapter 7: Form Fields Programming Radiobutton properties By setting the properties of Radiobutton objects, you can control at runtime such things as which radio button in a group is selected. For example, say that one of your forms has a group of three radio buttons radioself, radiospouse, and radiodependent and that when you created the radio buttons you chose to have radioself checked by default. However, at runtime you would like to be able to change which radio button is selected by default. Perhaps if the last time the form was submitted, the radioself radio button was checked, you would like the radiospouse radio button to be checked by default. You can make this change by using the Radiobutton method setchecked. Java if (...) { radioself.setchecked(false); radiospouse.setchecked(true); } HAHTtalk Basic if (...) Then radioself.setchecked False radiospouse.setchecked True End If The table below lists all of the methods commonly used to set and read the properties of radio buttons: Method setcheckedifvalueis setchecked Explanation sets the radio button s Checked variable to true if the argument you pass to the method matches the current value of the radio button. If this variable is set to true, the radio button is checked when its page is first displayed. sets the radio button s Checked variable to true unconditionally. If this variable is set to true, the radio button is checked when its page is first displayed. 175

197 Chapter 7: Form Fields Programming Method setgroupname getgroupname ischecked Explanation establishes the name of the button group to which a radio button belongs retrieves the name of the button group to which a radio button belongs determines whether a radio button s Checked variable is set to true StaticText properties There are a couple of common reasons for setting a property of a static-text field at runtime. For example, suppose that a static-text field on your page is a hypertext link and that you want to be able to set the destination of the link at runtime. You could use code similar to the following to accomplish this task. Java if (...) { staticlink.sethref(hahtsession().createstaticurl ("Destination.html","default")); } HAHTtalk Basic If (...) Then staticlink.sethref HahtSession.createStaticURL _ ("Destination.html", "default") End If As another example, consider the case where you ve read a currency value from a database and assigned it to a static-text field. By default, this value will be displayed without the proper formatting. To display the value as a dollar amount, you would normally set the Format property of the static-text field using the IDE. However, you could also format the value by calling the method setdisplaytext above the form containing the field: 176

198 Chapter 7: Form Fields Programming Java static1.setdisplaytext(com.haht.haht.format(static1.value, "Currency")); HAHTtalk Basic static1.setdisplaytext Format$(static1.value,"Currency") Note - For a list of the predefined formats you can use in this call, see Chapter 14, Working with Form Fields, in the HAHTsite IDE and IP User s Guide. The table below lists the methods most commonly used to set and read the properties of StaticText objects. Method setdisplaytext setescapehtmlchars sethref setlinkid Explanation controls the string to be displayed in a static-text field without changing the underlying value of the field. Usually, this string is a reformatted version of the field s value. You can reformat this field s value using the Format$ function (HAHTtalk Basic) or the format method (Java). determines whether characters such as < and > in a static text field s value are interpreted as being part of an HTML tag or not. If an object s mescapehtmlchars variable is set to true (the default), these characters are interpreted as HTML and are used in formatting the non-html portion of the value. If the variable is set to false, the characters are displayed as part of the value. used with static text that is (the default case)also a link. Establishes the URL of the page being linked to. used with static text that is also a link. Sets the project ID of the page being linked to. 177

199 Chapter 7: Form Fields Programming Method settarget gethref getlinkid gettarget isescapehtmlchars Explanation used with static text that is also a link. Establishes the frame in which to display the page being linked to. used with static text that is also a link. Returns the URL of the destination page. used with static text that is also a link. Returns the project ID of the destination page. used with static text that is also a link. Returns the name of the frame in which the destination page will be displayed. returns true if HTML special characters are being interpreted as such TextArea properties A text-area object s properties enable you determine at runtime the size of the text area and whether word wrap is turned on or off. The table below lists the methods that you use to set and read these properties. Method setcols setrows setwordwrap getcols getrows iswordwrap Explanation establishes the number of columns in the text area establishes the number of rows in the text area turns word wrap on or off. If word wrap is off, your text remains on one line until you type Enter. returns the number of columns in a text area returns the number of rows in a text area determines whether word wrap is on or off Textbox properties Being able to set text-box properties at runtime is handy for many tasks, including internationalization. For instance, the code below enables you to set 178

200 Chapter 7: Form Fields Programming the size of a Phone field to 12 if the user is working in the United States and to 16 if the user is working in France: Java if (language == "English") { txtphone.setsize(12); } else if (language == "French") { txtphone.setsize(16); } else {... } HAHTtalk Basic If (language = "English") Then txtphone.setsize 12 ElseIf (language = "French") Then txtphone.setsize 16 Else... End If The table below lists the most useful of the methods you can use to set and read the properties of Textbox objects. Method sethidden setmaxlength setpassword Explanation sets a Textbox object s Hidden variable to true or false. If this variable is set to true, the text box becomes a hidden form field; otherwise, it s a regular text box. Primarily used for compatibility with HAHTsite 3.x. establishes the maximum number of characters that can be entered in the field used to indicate that a text box is a password field. When you enter characters in a password field, they are not echoed literally. 179

201 Chapter 7: Form Fields Programming Method setsize getmaxlength getsize ishidden ispassword Explanation determines the width of the text box in characters, that is, how many characters you can view at once returns the maximum number of characters that can be entered in the field returns the width of the field in characters returns the value of the object s Hidden variable, which determines whether the text box is a hidden field returns the value of the object s Password variable, which determines whether the field is a password field or not Calculating form-field values Suppose that you ve developed a form to display information stored in a database concerning the quarterly sales totals for your sales people. A data agent on your HTML page retrieves each sales person s name, employee number, and quarterly sales figures from a database and displays them in your form. 180

202 Chapter 7: Form Fields Programming This is fine. But suppose you also want the form to display each sales person s total sales for the fiscal year to date. This is not the type of value that you would store in your database because it can easily be calculated from the quarterly sales figures. The remainder of this section explains how to perform this type of calculation and display the result using HAHTsite. Suppose your HTML page contains a heading, followed by a data agent, followed by a form. If you add code between the data agent and the form, that code will be executed: after the data agent has performed the most recently requested command, such as Move Next before the data retrieved by the data agent is actually displayed in the form You can use methods of the form-field classes used in the form to read and set the values that will be displayed in the form. Assume that you want to take the quarterly sales figures retrieved by the data agent, calculate the yearly total, and display that total in a static-text field labeled Year-to-Date Sales. You can do this using the code shown below. 181

203 Chapter 7: Form Fields Programming Java try { double salesq1 = (new Double(staticFirstQtrSales.getValue())).doubleValue(); double salesq2 = (new Double(staticSecondQtrSales.getValue())).doubleValue(); double salesq3 = (new Double(staticThirdQtrSales.getValue())).doubleValue(); double salesq4 = (new Double(staticFourthQtrSales.getValue())).doubleValue(); double salescy = salesq1 + salesq2 + salesq3 + salesq4; String salescystr = Double.toString(salesCY); staticyearsales.setvalue(salescystr); } catch ( NumberFormatException e ) { out.println("exception = " + e.getmessage()); } HAHTtalk Basic Dim Q1Sales As Double Dim Q2Sales As Double Dim Q3Sales As Double Dim Q4Sales As Double Dim FYSales As Double Q1Sales = Val(staticFirstQtrSales.getValue()) Q2Sales = Val(staticSecondQtrSales.getValue()) Q3Sales = Val(staticThirdQtrSales.getValue()) Q4Sales = Val(staticFourthQtrSales.getValue()) FYSales = Q1Sales + Q2Sales + Q3Sales + Q4Sales staticyearsales.setvalue Str$(FYSales) This code uses the getvalue method of the quarterly sales static-text objects to obtain the quarterly sales figures. The code then sums the quarterly figures and calls the setvalue method to set the value of a year-to-date-sales static-text field. When the form is displayed, the sum will be displayed in the appropriate field. 182

204 Chapter 7: Form Fields Programming For more information about setting and reading form field attributes using the setvalue and getvalue methods, see Setting and getting form-field properties on page 161. Calling user code from a button Similar to the way in which your application can call a subroutine associated with a form at the time you submit the form, you can have your application execute user code associated with a button when a form is submitted as a result of that button being clicked. These two features give you similar capabilities; in fact, the example presented in Calling a subroutine from a form on page 134 (writing a BLOB to a database) could just as well have been handled by user code associated with a button. However, there are also important differences between the two methods of calling user code. These differences are discussed in Code associated with a button versus code associated with a form below. This section also covers the mechanics of configuring a button to have a Submit Action of User Code. Code associated with a button versus code associated with a form Many tasks can be handled in either a subroutine associated with a form or user code associated with a particular button; in both cases, HAHTsite executes code when a form is submitted. However, it s important to understand the 183

205 Chapter 7: Form Fields Programming differences between these two actions and how the actions relate to one another. The obvious differences are that: a subroutine associated with a form is executed every time its form is submitted, while user code associated with a button is executed only when its form is submitted as a result of a particular button being pressed only one subroutine can be associated with a form while you can associate different subroutines with different form buttons One thing, however, might not be so obvious. On a single page, you can t use both a form action of Subroutine and a button action of User Code. This fact has to do with the way in which command handlers for buttons are generated. If the form s action is not Automatic/SELF, HAHTsite does not even generate a command handler for a form button, so any subroutine you associated with that button will never be called. You must loop back to the page on which you began before the user code associated with a button can be executed. Configuring a button to call user code To configure a button so that user-supplied code is called when the button is selected, follow these steps. To configure the button: 1 Double-click the form button to bring up the Form Field Properties window. 184

206 Chapter 7: Form Fields Programming 2 From the Action combo box, select the User Code option. A group of fields labeled Subroutine appears in the window. 3 In the Definition field, enter the name of a Basic subroutine or a Java method. In a Basic project, you can enter the name of any subroutine in the project, along with any required parameters. In a Java project, you must adhere to the following rules: You must enter the name of a method defined on the current page. This means that you must have used the page s Server-side Code view to enter your code. Enter an argument list. The argument list can be empty, but the parentheses must be present. Don t terminate your call with a semicolon. The code generator adds a semicolon for you. 4 Select the OK button. 185

207 Chapter 7: Form Fields Programming 186

208 Data-Agent Programming 8 Data agents and command handlers Calling data-agent methods at runtime Setting a data agent s command Performing a data-agent action Getting and setting the values of a data agent s fields Getting a reference to a data agent s connection Dealing with recordsets Getting parameters to stored procedures Refreshing a data agent s data Sorting records Filtering records Handling errors Enabling tracing The structure of a command handler Modifying a command handler Where to add code to a command handler Examples of adding code to a command handler Changing the flow of control in a command handler Example of changing the flow of control

209 Chapter 8: Data-Agent Programming Data agents and command handlers As you know if you ve created a HAHTsite page that links a form to a database, HAHTsite uses objects called data agents to: get an ADO recordset from a data source populate form fields in a form using a set of bindings defined in the data agent HAHTsite performs actions against the data agent s recordset when a user clicks a form button. For example, if the user clicks a Move Next button, code generated by HAHTsite calls the data agent s performaction method using an argument that indicates that the data agent should change its current record. Once the data agent s record pointer has been updated, the page can exit. The next time the page is run, the data agent will populate the form with data from the new current record. 188

210 Chapter 8: Data-Agent Programming The code generated to perform the action associated with a form button is called a command handler. Each button has its own command handler, and this method or subroutine performs the following tasks: If the Submit Action associated with the clicked button was Insert or Update, the command handler binds the data in the form to fields in the data agent s current record. If the action was Query or Find, the command handler fills in the Query or Find criteria. In all cases, the command handler performs the requested operation. If the operation was successful, the command handler calls the button s success page. If the operation was not successful, the command handler calls the button s failure page. The remainder of this chapter discusses two important ways in which you can customize pages that include data agents: You can call data-agent methods directly by placing Java or HAHTtalk Basic code on your page (Server-side Code view). In this view, you ll see two methods or subroutines named dataagent_onprerun and dataagent_onpostrun. When you execute your page, dataagent_onprerun executes immediately before the dataagent.run routine executes. (dataagent.run executes the data agent s initial command, if necessary, and opens the data agent s recordset.) The dataagent_onpostrun routine executes immediately after dataagent.run completes before any data retrieved from the data source has been bound to form fields. The dataagent_onprerun method or subroutine is a good place to do such things as change the data agent s command, and the dataagent_onpostrun routine gives you an opportunity to examine the values in the data agent s current record before the values in that record are bound to form fields. For further information about the DataAgent methods you can call from these routines, see Calling data-agent methods at runtime on page 190. You can customize the command handlers that HAHTsite generates to control what happens when a user clicks a form button. You can add functionality to these command handlers or change the normal flow of control in them. For additional information on this subject, see The structure of a command handler on page 212 and Modifying a command handler on page

211 Chapter 8: Data-Agent Programming Calling data-agent methods at runtime The DataAgent class includes a number of methods that enable you to control the behavior of a data agent at runtime. This section contains information about the most frequently used of these methods. This subset of methods allows you to: set the command that a data agent will use to get its recordset perform a data-agent action, such as inserting a record get or set the value of a field in a data agent s recordset get a reference to a data agent s connection get a reference to a data agent s recordset get the values of a stored procedure s output parameters refresh a data agent s data sort a data agent s records filter the records going in to the data agent s recordset handle a data agent s errors enable tracing for a data agent Setting a data agent s command The command associated with a data agent determines how the data agent obtains its recordset. This command can be a database table name, the name of a stored procedure, the name of a view, or (if the data agent is connected to a relational database) a SQL statement. You set such a command when you create a data agent using the IDE; however, you can override this original command using the DataAgent class s setcommand method. For example, say that you have a project that displays records from an employee-information database and that the data agent in your project uses a table name (Employees) as its command. You could quickly modify this project to display information only about employees from North Carolina by adding code similar to the following to your page s dataagent_onprerun routine (Server-side Code view). Java da1.setcommand("select * FROM Employees WHERE State = 'NC'"); da1.setcommandtype (com.haht.ado.commandtypeenum.adcmdtext); 190

212 Chapter 8: Data-Agent Programming HAHTtalk Basic da1.setcommand "SELECT * FROM Employees WHERE State = 'NC'" da1.setcommandtype ADO_CommandTypeEnum_adCmdText In this case, the data agent s command is being changed from a table name to a SQL statement. Note that you provide the new command using the setcommand method and that you use the setcommandtype method to specify the type of the new command. (You don t need to specify the type if the command type isn t changing.) The table below shows the Java class variables (constants) that you can use with the setcommandtype method in Java projects. Constant CommandTypeEnum.adCmdStoredProc CommandTypeEnum.adCmdTable CommandTypeEnum.adCmdText CommandTypeEnum.adCmdUnknown Meaning The command is the name of a stored procedure. The command is the name of a table or a view. The command is a textual command, such as a SQL statement. The command might also be a command requesting data from a nonrelational data source. The type of the command is unknown. In HAHTtalk Basic projects, you use similar constants, but the constants have slightly different names: ADO_CommandTypeEnum_adCmdStoredProc ADO_CommandTypeEnum_adCmdTable ADO_CommandTypeEnum_adCmdText ADO_CommandTypeEnum_adCmdUnknown The Basic constants are defined in the file ADOConstants.hbh, which HAHTsite automatically includes in the generated code for every page that contains a data agent. 191

213 Chapter 8: Data-Agent Programming Note - These constants are defined so that Basic projects do not have to incur the overhead of creating a Java class object in order to set a data agent s command type. That s all there is to changing a data agent s command. However, there are a couple of side effects of using the setcommand method that you should be aware of: If your command is the name of a stored procedure, any pre-fetch filtering or sorting operations are changed to post-fetch filtering or sort operations. This change is necessary because pre-fetch operations can modify the command text by adding a WHERE or ORDER BY clause, which is inappropriate for a stored-procedure call. If you change the command from a non-sql command to a SQL command, the data agent s misstandardsql member variable remains set to false until you explicitly change it. If you are performing pre-fetch filtering or sorting, you should change the value of this variable by calling setisstandardsql with a parameter of true. Pre-fetch operations are usually more efficient if misstandardsql is set to true. If the data agent whose command you are setting is being used to populate a form (which is typically the case), the data agent s notion of which Page Items (form fields) are bound to which Data Items (fields in the data agent s recordset) must be taken into consideration. That is, the recordset retrieved by the new command must contain a field with the appropriate name and data type for each of the data agent s Data Items so that the data agent can populate the corresponding form fields. If the original data-agent command was to call a stored procedure and the new command is to call a different stored procedure, the two stored procedures must have the same parameters, or they need to be modified. Performing a data-agent action A data agent usually performs actions, such as changing the current record or updating a record, when a user clicks a form button whose target is that data agent. The data agent also performs an action the first time that the page on which it appears is run. All this is typically handled with generated code. However, it s also possible to write code that causes the data agent to perform an action: when a form button is clicked when the data agent s page is first displayed The following sections explain in more detail how to write this type of code. 192

214 Chapter 8: Data-Agent Programming Performing data-agent actions Typically, a data agent performs an action when the command handler associated with a form button calls the data agent s performaction method. It s also possible to call this method directly. The two prototypes for this method are shown below: boolean performaction(int anaction) boolean performaction(int anaction, java.lang.object anactionarg) The first form of the method takes as its argument a constant. In Java projects, this constant is a final class variable of the class com.haht.project.datamanager.dmconstants. The constants you can use with the first form of this method are shown in the table below. Constant ACTION_ADD_NEW ACTION_CANCEL_UPDATE ACTION_CLEAR ACTION_DELETE ACTION_FIND ACTION_INSERT ACTION_MOVE_FIRST ACTION_MOVE_LAST ACTION_MOVE_NEXT Action adds a new record to the data agent s recordset enables you to cancel an Insert operation after a new record has been created, but before the record has been updated clears the form fields being populated by the data agent deletes the data agent s current record performs an ADO Find operation. Finds the first record in the data agent s recordset that meets a single criterion and moves the current-record pointer to that record. You must have set up your find criterion (by calling setfindcriteria) before you perform this action. inserts the values of the form fields being populated by the data agent into a new record in the data agent s recordset makes the first record in the data agent s recordset the current record makes the last record in the data agent s recordset the current record makes the next record in the data agent s recordset the current record 193

215 Chapter 8: Data-Agent Programming Constant ACTION_MOVE_PREVIOUS ACTION_NEXT_RECORDSET ACTION_NONE ACTION_QUERY ACTION_REQUERY ACTION_UPDATE Action makes the previous record in the data agent s recordset the current record loads a new recordset into the data agent the next in a series of recordsets retrieved by the data agent s last command no action returns a set of records (from the data agent s recordset) that meet a set of criteria you supply. You must establish these criteria by making one or more calls to setquerycriteria before you perform this action. causes the data agent to get a new recordset by calling the data agent s current command (established by the last call to setcommand) updates the data agent s current record You use similarly named constants in a HAHTtalk Basic project. You just need to prepend DMConstants_ to a name shown in the table above. For example, to request a move-next action, you would use the constant DMConstants_ACTION_MOVE_NEXT. These Basic constants are defined in the file SOMConstants.hbh, which is included in the generated code for every page with a data agent. There are also two constants that require or may take an associated argument: ACTION_EXEC_COMMAND and ACTION_FIND (DMConstants_ACTION_EXEC_COMMAND and DMConstants_ACTION_FIND in Basic projects). You use these constants with the second form of the performaction method. (The constant is the first argument to the method.) The constant ACTION_EXEC_COMMAND causes performaction to execute the command that you supply as an argument (the second argument to performaction). The argument associated with ACTION_EXEC_COMMAND can be a string or null. If the argument is a string, it must be the command that you want the data agent to use to get a new recordset. This command can be the name of a table, the name of a stored procedure, and so forth. (This argument is analogous to the argument to the setcommand method.) If the argument is null, performaction executes the last command set using the setcommand method. 194

216 Chapter 8: Data-Agent Programming The constant ACTION_FIND causes performaction to find the next record in the recordset that meets the criterion specified in its associated argument, a string. This string must have the form columnname operator value. For example, the string "State = 'NC'" is a valid find-criteria string. Note - Both a connection and a recordset must be open before you call performaction with any constant other than ACTION_NONE or ACTION_EXEC_COMMAND. In addition, a connection must be open before you call performaction with the constant ACTION_EXEC_COMMAND. Here s an example of how you might use the performaction method in your project. Say that your application calls a stored procedure that returns two recordsets and that the two recordsets have the same columns. You can only work with the first recordset using the standard data agent commands. To load the second recordset into the data agent, you would need to call performaction with the ACTION_NEXT_RECORDSET argument. For example, you could add code to the command handler for a Move Next button to have your application load the second recordset when a user clicks a Move Next button while looking at the last record in the first recordset. Note - For detailed information about command handlers, see The structure of a command handler on page 212 and Modifying a command handler on page 216. Setting a data agent s initial command It s also possible to set a data agent s initial command programatically. You do this using the setinitialaction method, whose prototype is shown below: void setinitialaction(int anaction) This method takes as its argument a constant defined in the class com.haht.project.datamanager.dmconstants (Java projects) or in the file SOMConstants.hbh (HAHTtalk Basic projects). The constants most commonly used with this method are shown in the table below. Java DMConstants.ACTION_CLEAR DMConstants.ACTION_MOVE_FIRST DMConstants.ACTION_MOVE_LAST DMConstants.ACTION_MOVE_NEXT DMConstants.ACTION_MOVE_PREVIOUS HAHTtalk Basic DMConstants_ACTION_CLEAR DMConstants_ACTION_MOVE_FIRST DMConstants_ACTION_MOVE_LAST DMConstants_ACTION_MOVE_NEXT DMConstants_ACTION_MOVE_PREVIOUS 195

217 Chapter 8: Data-Agent Programming For a complete list of the constants you can use with the setinitialaction method, see Performing data-agent actions on page 193. Since a data agent s initial action can be set using the IDE, you will generally only use this method if you want to change the initial action based on some user preference. For example, some users might want to browse a set of records beginning with the first record, while others might want browse the records starting with the last record. Java if (...) { da1.setinitialaction (com.haht.project.datamanager.dmconstants.action_move_first); } else { da1.setinitialaction (com.haht.project.datamanager.dmconstants.action_move_last); } HAHTtalk Basic If (...) Then da1.setinitialaction DMConstants_ACTION_MOVE_FIRST Else da1.setinitialaction DMConstants_ACTION_MOVE_LAST End If Getting and setting the values of a data agent s fields The DataAgent class includes a number of methods that enable you to set and retrieve the values of fields in a data agent s recordset. These methods can be useful in command handlers where you need to set or test the value of a field before a data-agent action is performed. For instance, a code example presented later in this chapter see Altering a form-field value before binding on page 218 illustrates how you might set a field value in a command handler to ensure that a field containing an empty string is given a reasonable default value before its record is inserted in a database. The table below lists the get and set routines that are available. 196

218 Chapter 8: Data-Agent Programming Method getfieldstring getfieldstringbynameor Ordinal getfieldvariant getfieldvariantbynameor Ordinal isfieldnull setfieldstring setfieldtonull Explanation retrieves the value of a field in the current record as a String. The single argument to this method can be a String containing a field name or an integer representing the position of the field within the record. retrieves the value of a field in the current record as a String. The single argument to this method must be a String containing a field name or a positional number. retrieves the value of a field in the current record as a Variant. The single argument to this method can be a String containing a field name or an integer representing the position of the field within the record. retrieves the value of a field in the current record as a Variant. The single argument to this method must be a String containing a field name or a positional number. determines whether the value of a field in the current record is null. The single argument to this method can be a String containing a field name or an integer representing the position of the field within the record. The method s return value is a boolean. sets the value of a field in the current record using a String. The first argument to this method can be a String containing a field name or an integer representing the position of the field within the record. The second is the String to which the field should be set. sets the value of a field in the current record to null. The single argument to this method can be a String containing a field name or an integer representing the position of the field within the record. 197

219 Chapter 8: Data-Agent Programming Method setfieldvariant Explanation Sets the value of a field in the current record using a Variant. The first argument to this method can be a String containing a field name or an integer representing the position of the field within the record. The second is the Variant to which the field should be set. Note - It s a good idea to call the data-agent method isfielddataavailable before reading or writing a field especially in a HAHTtalk Basic project, where the try/catch mechanism is not available. A get or set operation could fail if you re working with an empty recordset, have reached EOF, etc. Getting a reference to a data agent s connection Using the DataAgent class s getconnection method, you can get a reference to the Connection object being used by the data agent. Using this Connection object, you can perform all of the actions associated with that object, such as opening or closing the connection, executing a command, or managing a transaction. You can also examine the properties of the connection to determine such things as: the timeout value for establishing the connection the timeout value for executing a command whether the connection is currently open or closed The prototype for the getconnection method is shown below: com.haht.ado.abstract.connection getconnection() Dealing with recordsets The interface to DataAgent objects enables you to perform several types of actions related to recordsets. For example, you can: limit the maximum number of records retrieved by a data agent s command make a recordset read only get a reference to the ADO Recordset object associated with the data agent 198

220 Chapter 8: Data-Agent Programming load a session recordset at session start Limiting the maximum number of records To limit the maximum number of records returned by a data-agent command, you use the method setmaxrecords: void setmaxrecords(int amax) For example, the code below limits the size of the data agent s recordset to 100 records. Java if (!da1.getinitialactionhascompleted()) { da1.setmaxrecords(100); } HAHTtalk Basic If (da1.getinitialactionhascompleted() = False) Then da1.setmaxrecords 100 End If Note - The call to getinitialactionhascompleted is necessary to ensure that the limit on the number of records is set only the first time the page is run (before the data agent s initial action has completed). If you attempt to set the limit each time the page is run, you ll get an error the second time the page is run saying that this property can t be set while a recordset is open. Making a recordset read only You can make a recordset read only by calling a data agent s setreadonly method. If you call this method, users will not be able to perform operations that change the data in a recordset, such as Insert. In addition, making a recordset read only makes certain ADO optimizations possible. The prototype for the setreadonly method is shown below: void setreadonly(boolean readonly) 199

221 Chapter 8: Data-Agent Programming Getting a reference to a data agent s recordset In addition to setting a maximum number of records and making a recordset read only, you can also get a reference to a data agent s recordset using the method getrecordset: com.haht.ado.abstract.recordset getrecordset() Once you have this reference, you can use all of the recordset methods and properties defined by ADO. For example, you ll have access to methods that enable you to: cancel an update move to any record in the recordset refresh the data in the recordset without requirying the data source check for EOF and BOF Loading a session recordset at the start of a session If your application uses a session recordset and you need to access data in that recordset before the user visits a page containing a data agent whose Data Source is that session recordset, you can load data into the session recordset at the time a user session begins. To do this, you add code to an on-start method or function. This method must: get a reference to the session recordset (a data agent) set some data-agent properties, such as the data agent s connection and its command. call the data agent s run method In a Java project, you must add the code that performs these tasks to the HahtSession class s onstart method. (This class is defined in the file HahtSession.java, which is in your Session folder.) The code below provides an example of how you might implement the onstart method. 200

222 Chapter 8: Data-Agent Programming Java public void onstart(com.haht.project.sessionevent anevent) { com.haht.project.datamanager.dataagent sessionda = ((HahtSession)Haht.getSession()).getEmployees(); sessionda.setconnectionbyname( EmployeeConn ); sessionda.setcommand("select * FROM Employees"); sessionda.setcommandtype (com.haht.ado.commandtypeenum.adcmdtext); sessionda.setisstandardsql(true); sessionda.setinitialaction (com.haht.project.datamanager.dmconstants. ACTION_MOVE_FIRST); sessionda.run(); } In your own code, you ll need to replace the call to getemployees with a call to getsessionrecordset where SessionRecordset is the name of your session recordset. In a HAHTtalk Basic project, you must add a code page to your project, and in this file define a public function called HahtSessionOnStart. See the example below. 201

223 Chapter 8: Data-Agent Programming HAHTtalk Basic #include "Session\GeneratedSession.hbh" #include <ADOConstants.hbh> #include <SOMConstants.hbh> Public function HahtSessionOnStart As Boolean Dim sessionda As Object Set sessionda = Employees sessionda.setconnectionbyname "EmployeeConn" sessionda.setcommand "SELECT * FROM EMPLOYEES" sessionda.setcommandtype ADO_CommandTypeEnum_adCmdText sessionda.setisstandardsql True sessionda.setinitialaction DMConstants_ACTION_MOVE_FIRST sessionda.run HahtSessionOnStart = True End function Getting parameters to stored procedures The DataAgent class contains several methods that are useful for getting the value of an output parameter (or an input/output parameter) of a stored procedure or the return value of a stored procedure. These methods are shown in the table below. Method getparameterstring(int) getparameterstring(string) getparametervariant(int) Explanation retrieves the value of a parameter or the return value of a stored procedure as a String. The argument to this method is an index into a set of parameters. retrieves the value of a parameter or the return value of a stored procedure as a String. The argument to this method is a String containing the name of a parameter. retrieves the value of a parameter or the return value of a stored procedure as a Variant. The argument to this method is an index into a set of parameters. 202

224 Chapter 8: Data-Agent Programming Method getparametervariant(string) Explanation retrieves the value of a parameter or the return value of a stored procedure as a Variant. The argument to this method is a String containing the name of a parameter. One restriction you should be aware of here is that a stored procedure s output parameters may not be available to your application immediately after the stored procedure is executed. For example, consider the following SQL Server stored procedure: CREATE PROCEDURE integer OUTPUT AS SELECT cust_id, paint_supplier.name AS brand, color, gallons FROM paint_order, paint_supplier WHERE color and paint_supplier.supplier_id=paint_order.supplier_id FROM paint_order WHERE color The first SELECT statement in this stored procedure returns a recordset. Only after your application has traversed this recordset (or at least until you ve done a Move Last), you cannot get the value of sumgal. Once you ve accessed the last record in the recordset, the output parameter becomes available. Refreshing a data agent s data The Advanced tab in the IDE s Data Agent Properties dialog enables you to check a check box to specify that a data agent command should be reexecuted each time its page is run. Reexecuting this command, of course, refreshes the data in the data agent s recordset. You can also request that the data agent execute its command each time its page is run using the data agent s setrefreshonpagerun method. Java da1.setrefreshonpagerun(true); 203

225 Chapter 8: Data-Agent Programming HAHTtalk Basic da1.setrefreshonpagerun True You can place this call in the Custom constructor code section of the Server-side Code view of your page. Note - The DataAgent class also contains a getrefreshonpagerun method that retrieves the value of the data agent s refresh property. Sorting records If you have a page that includes an ADO report, and that report uses grouping, the records to be displayed in the report must be sorted. This sorting can take place on the database server, or it can be performed by the HAHTsite Application Server. You can control where the sorting takes place by calling the appropriate method of the DataAgent class, either setpresort (database) or setpostsort (Application Server). By default, HAHTsite generates a call to setpostsort on a page that contains a report with groups, for example: daemployees.setpostsort("lastname", "firstname"); This statement indicates that the sorting should be done on the Application Server. This type of sorting is the default because of a restriction on sorting records on the database server: If a SELECT statement refers to two or more columns that are in different tables but have the same name, a pre sort will not work correctly. In addition, you must always use a post sort if your data source is not a relational database. Having said that, if you are getting data from a relational database and won t run into the naming-conflict problem mentioned above, you should let your database server do the sorting to increase the efficiency of your application. To make this change, add code that calls the data agent s setpresort method in your page s constructor or dataagent_onprerun method. See the code below for an example: Java if (!da1.getinitialactionhascompleted()) { daemployees.setpresort(daemployees.getpostsort()); daemployees.setpostsort(""); } 204

226 Chapter 8: Data-Agent Programming HAHTtalk Basic If (da1.getinitialactionhascompleted() = False) Then da1.setpresort da1.getpostsort() da1.setpostsort "" End If If the report page has not been run previously, this code calls the data agent s setpresort routine to indicate that the sorting should be done by the database server. The argument passed to this method is the argument that HAHTsite generated for its call to setpostsort in this case, "lastname", "firstname". Finally, the code calls setpostsort with an argument of the empty string so that records will not be sorted by the Application Server. Filtering records The IDE provides a nice graphical user interface you can use to specify the conditions a data agent should use to filter the records it retrieves as a result of a command. For example, you might want a data agent to retrieve information about sales orders placed after January 1, This type of filtering is easy and can be done on either the database server or the Applicatin Server but has one limitation: the same filters are used each time a particular data agent obtains a recordset. Suppose you have a project that enables users to view the orders placed by a particular customer during a specific period of time. The first page of the application presents a form that asks the user to specify a customer, a starting date, and an ending date. 205

227 Chapter 8: Data-Agent Programming Only after this form is submitted will you have the information you need to construct the necessary filter. Therefore, you must set up the filter programatically on the target page (the page that will contain your data agent and present the results of your query). Sample code for both a Java project and a HAHTtalk Basic project is shown below. 206

228 Chapter 8: Data-Agent Programming Java // // Conditional pre-filtering - use start, end date of previous // form IF the user filled either of them out. // if (arequest.geturlfieldexists("txtstartdate") &&!arequest.geturlfield("txtstartdate").equals("")) { dausersql.setprefilter (DMConstants.USER_FILTER_URLFIELD, "purchase_date", ">=", "txtstartdate", com.haht.ado.datatypeenum.addate); } if (arequest.geturlfieldexists("txtenddate") &&!arequest.geturlfield("txtenddate").equals("")) { dausersql.setprefilter (DMConstants.USER_FILTER_URLFIELD, "purchase_date", "<=", "txtenddate", com.haht.ado.datatypeenum.addate); } HAHTtalk Basic ' ' Conditional pre-filtering - use start, end date of previous form IF the user filled either of them out. ' If (arequest.geturlfieldexists("txtstartdate") AND _ arequest.geturlfield("txtstartdate") <> "") Then dapaint_order.setprefilter DMConstants_USER_FILTER_URLFIELD, _ "purchase_date", ">=", "txtstartdate", _ ADO_DataTypeEnum_adDate End If If (arequest.geturlfieldexists("txtenddate") AND _ arequest.geturlfield("txtenddate") <> "") Then dapaint_order.setprefilter DMConstants_USER_FILTER_URLFIELD, _ "purchase_date", "<=", "txtenddate", _ ADO_DataTypeEnum_adDate End If 207

229 Chapter 8: Data-Agent Programming This code calls the method setprefilter to indicate that the filtering should take place on the database server. This method is overloaded and can have the following signatures: public void setprefilter (int atype, String afield, String anop, String acompval) public void setprefilter (int atype, String afield, String anop, String acompval, Object amaster) public void setprefilter (int atype, String afield, String anop, String acompval, int adatatype) public void setprefilter (int atype, String afield, String anop, String acompval, Object amaster, int adatatype) The table below describes the parameters that the method takes. Parameter atype afield Description A constant that indicates the type of the comparison value to be used in the filter criterion, which has the form field operator comparisonvalue. In Java projects, you select a constant defined in com.haht.project.datamanager.dmconstants. The constants you can choose from are: USER_FILTER_CONSTANT - The comparison value is a constant. USER_FILTER_VARIABLE - The comparison value is the current value of a variable. USER_FILTER_URLFIELD - The comparison value is the value of a URL field. USER_FILTER_RS_FLD - The comparison value is the value of a field in a master recordset. In HAHTtalk Basic projects, the corresponding values are defined in the include file SOMConstants.hbh. These constants have the same names as their Java counterparts except that you must prepend DMConstants_ to each name. For instance, the HAHTtalk Basic equivalent of USER_FILTER_CONSTANT is DMConstants_USER_FILTER_CONSTANTS. The name of a column in your data agent s recordset. 208

230 Chapter 8: Data-Agent Programming Parameter anop acompval amaster adatatype Description An operator. The possible operators are: = < > <= >= <> LIKE IS NULL IS NOT NULL If you use one of the last two options for this parameter, there is no need to supply the acompval parameter. The value with which you want to compare the value of a field in your data agent s recordset. This value can be a constant, the value of variable, the value of a URL field, or the value of a field in a master recordset. In the last case, acompvalue should be the name of a field in a master recordset. The data agent containing the master recordset. You supply this value only if your atype parameter is USER_FILTER_RS_FLD. An ADO constant that specifies the data type of the comparison value. HAHTsite uses this argument to determine how to escape the comparison value. If you don t supply this argument, HAHTsite treats all comparison values as database strings; that is, it encloses them in single quotes. If the comparison value is of a data type that should not be single quoted, you must supply this argument. The DataAgent class also contains methods for setting up filtering to be done on the Application Server. These methods are named setpostfilter and have the signatures shown below: public void setpostfilter (int atype, String afield, String anop, String acompval) public void setpostfilter (int atype, String afield, String anop, String acompval, Object amaster) 209

231 Chapter 8: Data-Agent Programming The parameters to these methods are the same as those used with the setprefilter methods. Handling errors When a data agent attempts to perform an action and an error occurs, HAHTsite creates an ADO Error object. If several errors occur, several Error objects are created in a collection. The DataAgent class provides two methods that you can use to deal with such errors: geterrorcount and geterror: int geterrorcount() com.haht.ado.abstract.error geterror(int index) The method geterrorcount indicates the number of errors that occurred as a result of the data agent s last call to performaction or performinitialaction, and the geterror method returns a reference to one of the Error objects in the collection. Once you have a reference to an Error object, you can use the Error class s getdescription method to get a description of the error. Typically, you ll call these error methods from a command handler s prefailure event handler and then display your error information on a failure page. For a complete discussion of how to write this event handler and a complementary failure page, see Customizing a failure page on page 223. Enabling tracing In the IDE on the Advanced tab of the Data Agent Properties dialog you can turn on a data-agent feature called tracing. If you turn tracing on, HAHTsite writes to a log file information about the activity of the data agent. Part of a sample log file is shown below. 210

232 Chapter 8: Data-Agent Programming Starting trace at Mon Jan 04 12:09:14 CST 1999 DataAgent(da1).setInitialAction( movefirst) DataAgent(da1).setCommandType: new type=2 DataAgent(da1).setConnectionByName: id=employeeconn DataAgent(da1).performInitialAction: action=movefirst DataAgent(da1).openPendingConnections(ID): connection is non-null DataAgent(da1).performInitialAction: opening recordset if nonnull command. DataAgent(da1).openRS, opening RS, command=employees DataAgent(da1).openRS: Allocating new recordset DataAgent(da1).openRS: setting Max Records to 2 DataAgent(da1).openRS, after open, EOF=false, BOF=false DataAgent(da1).run: FieldDataAvailable =true DataAgent(da1).getFieldString(Last Name) DataAgent(da1).getFieldString: value='doe' DataAgent(da1).getFieldString(First Name) DataAgent(da1).getFieldString: value='john' DataAgent(da1).getFieldString(Street Addr) DataAgent(da1).getFieldString: value='4200 Six Forks Rd' DataAgent(da1).getFieldString(City) DataAgent(da1).getFieldString: value='raleigh' DataAgent(da1).getFieldString(State) DataAgent(da1).getFieldString: value='nc' DataAgent(da1).getFieldString(Zip) DataAgent(da1).getFieldString: value='27609' This is an all-or-nothing proposition. Once you turn tracing on, it remains on for the duration of a session. To limit the scope of the tracing, you can use the DataAgent class s settracing method: void settracing(boolean tracingstatus) For example, you might want to have tracing turned on only when a particular command handler is running. To achieve this result, simply turn tracing on at the beginning of the command handler and off at the end of the command handler. 211

233 Chapter 8: Data-Agent Programming The structure of a command handler In database applications, it s common for a page to include a data agent followed by a form. If such a form s action is Automatic/SELF and the form contains buttons, HAHTsite generates a form handler for the page. This form handler looks like this: 212

234 Chapter 8: Data-Agent Programming Java public void mapformtocmd (com.haht.project.request arequest, com.haht.project.response aresponse) { boolean bcmdhandlercalled = false; if (arequest.geturlfieldexists("btnmovefirst")) { Form1_btnMoveFirst_ch(aRequest, aresponse); bcmdhandlercalled = true; } else if (arequest.geturlfieldexists("btnmovenext")) { Form1_btnMoveNext_ch(aRequest, aresponse); bcmdhandlercalled = true; }... if (! bcmdhandlercalled) { geterrors().add ("Received form command did not invoke a command-handler", "form-handler"); run (arequest, aresponse); } } 213

235 Chapter 8: Data-Agent Programming HAHTtalk Basic Public Sub HS_EmployeeInfo_fH Dim bcmdhandlercalled As Boolean Dim thepage As Object, theerrors As Object Dim aresponse As Object Set aresponse = Haht.getResponse() On Error Goto HAHTErrorHandler_fH bcmdhandlercalled = False If (Haht.getRequest().getURLFieldExists("btnMoveFirst")) Then Form1_btnMoveFirst_ch bcmdhandlercalled = True ElseIf (Haht.getRequest().getURLFieldExists("btnMoveNext")) _ Then Form1_btnMoveNext_ch bcmdhandlercalled = True... End If If (Not bcmdhandlercalled) Then Set thepage = Haht.getPage() Set theerrors = thepage.geterrors() theerrors.add _ "Received form command didn't invoke a command-handler", _ "form-handler" Set thepage = Nothing Set theerrors = Nothing HS_EmployeeInfo End If End Sub This form handler simply looks at the incoming URL datastream when the user submits a form from a browser, determines which button was clicked, and calls a generated command handler that matches that button. In both Java and HAHTtalk Basic projects, a command handler has a name of the form buttonname_ch. It s important to understand the structure of a command handler because, as you ll see in the next section, these handlers are designed to be customized, and you need to understand where you can add your own code and how you can customize the flow of control. The tasks that a command handler performs are as follows: 1 Bind the data submitted with the form to fields in the recordset represented by the data agent that is the target of the command (button). 214

236 Chapter 8: Data-Agent Programming This data binding applies only to Insert and Update commands. (For Find and Query operations, the criteria to be used for the operation are established at this point.) 2 Execute the command associated with the button used to submit the form. 3 If the command succeeds, go to a success page. 4 If the command fails, go to a failure page. Without going into too much detail, the figure below shows you more specifically how HAHTsite would structure the command handler for a button named btnupdate on a form named Form1. Note - The method names used in this figure are taken from a Java project; however, a HAHTtalk Basic command handler is structured the same way. btnupdate_bindfields() { // Bind fields from URL to data-agent fields. } btnupdate_execaction() { // Execute action. if (action is successful) { stepvar=proceed_do_success_page } else { stepvar=proceed_do_failure_page } } Entry point btnupdate_ch() { btnupdate_bindfields() btunupdate_execaction() if (stepvar= =PROCEED_DO_SUCCESS_PAGE) { run success page } if (stepvar= =PROCEED_DO_FAILURE_PAGE) { run failure page } } 215

237 Chapter 8: Data-Agent Programming As you ll see in the next section, there are four places where you can add code to change the behavior of such a command handler. It s also possible to skip steps in the standard sequence of command-handler actions: 1 Bind data (Insert and Update only) 2 Execute action 3 Run success page 4 Run failure page The upcoming section, Modifying a command handler, explains in detail how to and why you would want to customize your command handlers. Modifying a command handler As was mentioned in The structure of a command handler on page 212, you can add code to a command handler in several places. In addition, the code you add can alter the flow of control in the command handler. This section contains the following subsections: Where to add code to a command handler on page 216 Examples of adding code to a command handler on page 217 Changing the flow of control in a command handler on page 225 Example of changing the flow of control on page 227 Where to add code to a command handler In each command handler in your application, there are either three or four places where you can add code. Command handlers for Insert and Update buttons have four such places, and most other command handlers have three. Here are the locations: Just before the command handler binds data from a URL to data-agent fields (Insert and Update command handlers only). To add code that will be executed at this point, you add statements to the generated function buttonname_onbind. Just before the command handler executes the command associated with the button used to submit the form. To add code that will be executed at this point, you add statements to the generated function buttonname_onexec. 216

238 Chapter 8: Data-Agent Programming Just before the command handler runs its success page. To add code that will be executed at this point, you add statements to the generated function buttonname_onsuccess. Just before the command handler runs its failure page. To add code that will be executed at this point, you add statements to the generated function buttonname_onfail. When you look at the Server-side Code view of your page, you ll see these empty functions just above the related command handler. You customize these functions by typing in the white areas just below the method or subroutine names. Any code you type in the white areas of the screen will be retained when the code for your page is regenerated. This will all probably make more sense when you look at an example or two of why you might add code to a command handler. You can find such examples in the next section, Examples of adding code to a command handler. Examples of adding code to a command handler This section presents several examples of how you can add functionality to a generated command handler: 217

239 Chapter 8: Data-Agent Programming The first example illustrates how to change a form-field value between the time the value is submitted and the time the command handler binds that value to a data agent. The second example is a variation of an example used in Chapter 6, Forms-Related Programming : it explains how to insert a Binary Large Object (BLOB) in a database using a command handler s prebind routine. The third example explains how to use a prefailure routine to customize a failure page. Altering a form-field value before binding When a user clicks an Insert or Update button on a form and a command handler is called, the command handler normally binds the data submitted to fields in the button s target data agent. However, you have a chance to intercept this data, and to change it in any way you like, before the data is bound to data-agent fields. You do this by adding code to your command handler s prebind routine: buttonname_onbind. For example, let s say that you have a project that: reads personal data submitted by potential subscribers from a temporary database allows you to insert subscriber records into a permanent database 218

240 Chapter 8: Data-Agent Programming If the subscriber did not supply a country name, you want to bind the value United States to the data agent s Country field before the normal binding occurs. (Normal binding will not affect the Country field because the Country text box is empty.). To accomplish this, you can add code to the Insert command handler s prebind function. See the code samples below. Java protected void btninsert_onbind (com.haht.project.request arequest, com.haht.project.response aresponse, com.haht.project.datamanager.dmhandlerinfo ahandlerinfo) { // Insert code to run before binding data to the command btninsert. if (arequest.geturlfield("txtcountry").equals("")) { da1.setfieldstring("country", "United States"); } } HAHTtalk Basic Private Sub btninsert_onbind(ahandlerinfo As Object) ' Insert code to run before binding data to the command btninsert. If (Haht.getRequest().getURLField("txtCountry") = "") Then dssubscriberinfo.setfieldstring "Country", "United States" End If End Sub This is a simple example, but it illustrates how to get a value submitted with a form before the form s values are bound to a data agent, and how to bind values to a data agent. For a lengthier example of how to customize a command handler s prebind routine, see Inserting a BLOB into a database below. Inserting a BLOB into a database This section presents another example of how you might customize a command handler s prebind method. Suppose you have a form that contains a File Upload form field. When a user runs your application, he or she will enter the path to an image file in the File Upload text field. When the user clicks the Insert button, you want to take this pathname, open the image file, and write the contents of the file to a BLOB field in your database. (The record 219

241 Chapter 8: Data-Agent Programming containing the image will also contain a picture name that you can use to identify the image.) Since HAHTsite doesn t generate code for inserting a large binary object into a database, you must add code similar to the following to a command handler to insert this object in your database. 220

242 Chapter 8: Data-Agent Programming Java protected void btninsert_onbind(com.haht.project.request arequest, com.haht.project.response aresponse, com.haht.project.datamanager.dmhandlerinfo ahandlerinfo) { // // Get filename of uploaded image, open it, and prepare to // appendchunk it into the recordset field // String spicturefilename = Haht.getApplication(). getuserroot() + '/' + arequest.geturlattachment ("mfupicture"); java.io.file picturefile = new java.io.file (spicturefilename); FileInputStream picturestream; try { picturestream = new FileInputStream (picturefile); } catch (java.io.filenotfoundexception e) { arequest.setuserprop("errormessage", "Uploaded file not found!"); ahandlerinfo.setproceedaction (DMConstants.PROCEED_DO_FAILURE_PAGE); return; } // Recordset has done addnew, so we have a Field to put // picture in. Get picture field for appending data into // Field picturefld = danameandpict.getrecordset(). getfield("picture"); Field namefld = danameandpict.getrecordset(). getfield("name"); namefld.setstring(arequest.geturlfield("txtname")); 221

243 Chapter 8: Data-Agent Programming Java // // Allocate a buffer and read until we're done // byte [] picturebuf = new byte[bufsize]; int nbytesread; int nbytestotal = 0; do { try { nbytesread = picturestream.read (picturebuf); nbytestotal += nbytesread; if (nbytesread > 0) picturefld.appendchunk (picturebuf, nbytesread); } catch (java.io.ioexception e) { arequest.setuserprop("errormessage", "Error occurred while reading/writing image"); danameandpict.getrecordset().cancelupdate(); ahandlerinfo.setproceedaction (DMConstants.PROCEED_DO_FAILURE_PAGE); try { picturestream.close(); } catch (java.io.ioexception e2) { } return; } } while (nbytesread > 0); 222

244 Chapter 8: Data-Agent Programming Java } // // Close file, continue // try { picturestream.close(); } catch (java.io.ioexception e) { } Note - Appendix C, Code Examples, presents code you could use in a HAHTtalk Basic project to perform this same task. See the section Modifying a command handler on page 370. If you ve read Chapter 6, Forms-Related Programming,, you ll recognize this example as a variation of an earlier example that illustrated how to write a BLOB to a database by calling a subroutine as the action of a form. Note that several steps taken in the earlier example are not necessary in this one, including: opening a connection opening a recordset adding a new record to the recordset Because this section s example code is being called from an Insert button s command handler, these actions have already been performed at the time the code is called. Customizing a failure page Suppose you implemented the example in Inserting a BLOB into a database on page 219, which uses a custom Insert command handler to insert a BLOB in a database, and the insertion failed. You could use the IDE to customize the Insert button so that an error page would be run if the insertion failed, but how would you write some custom content to that error page? This section tells you how. The simple answer is that you can add code to the Insert button s prefailure routine to make customizing the failure page possible. See the sample code below. 223

245 Chapter 8: Data-Agent Programming Java protected void btninsert_onfail (com.haht.project.request arequest, com.haht.project.response aresponse, com.haht.project.datamanager.dmhandlerinfo ahandlerinfo) { // Insert code to run after the btninsert command fails. arequest.setuserprop("errormessage","insertion of picture " + arequest.geturlfield("txtname") + " failed."); } Note - In a HAHTtalk Basic project, you could use a global variable to hold the error message. This code uses the setuserprop method of the Request object passed to the method to set a user property associated with the Request object. The two arguments to this method are the name of a user property (which is user defined) and the value of that property. Since this Request object is passed to the failure page s run method, that run method can use the Request object s getuserprop method to get this message in order to display it. The Normal view of a sample failure page is shown below. Java // Check to see if the message was passed in // Request.UserProp("Message") or ("ErrorMessage") if (arequest.getuserprop("errormessage")!= null) seterrormessage ((String) arequest.getuserprop ("ErrorMessage")); else if (arequest.getuserprop("message")!= null) setmessage ((String) arequest.getuserprop("message")); // Display success or error message here, using property set by // caller. out.print ("<DIV ALIGN=CENTER><H2>"); if (mmsgiserror) out.print("<font COLOR=red>sMsg</FONT>"); else out.print("<font COLOR=black>sMsg</FONT>"); out.print("</h2></div>"); smsg = ""; mmsgiserror = false; 224

246 Chapter 8: Data-Agent Programming This page checks the Request object passed to it for an error message ( ErrorMessage ) or a success message ( Message ). If the user property ErrorMessage has been set, the page gets the value of that property and uses the user-defined method seterrormessage to set the value of the user-defined variable smsg. This method and member variable are defined in the Server-side Code view of the failure page. Java // private methods /** * Set displayed message text, and mark for display as non-error **/ public void setmessage(string amsg) { smsg = amsg; mmsgiserror = false; } /** * Set displayed message text, and mark for display as error **/ public void seterrormessage (String amsg) { smsg = amsg; mmsgiserror = true; }... // private member variables private String smsg = ""; private boolean mmsgiserror = false; This example requires you to write a little code in three different places, but should be a very useful example if you re customizing your application s command handlers. Changing the flow of control in a command handler In addition to adding code to a command handler, you can change the flow of control in the command handler. The normal flow of control is shown below. 225

247 Chapter 8: Data-Agent Programming You can easily change this flow, however, by setting a constant in a command handler s prebind, preexecute, presuccess, or prefailure routine. Here s how the mechanism works. When a command handler calls one of the methods or subroutines shown below, it passes to that subroutine or method an object of type DMHandlerInfo: ButtonName_onBind ButtonName_onExec ButtonName_onSuccess ButtonName_onFail One of this object s member variables, mproceed, stores a constant that indicates what action the command handler should take after the user-defined routine exits. This constant is preset to PROCEED_DO_NEXT_STEP when the user-defined routine is called. The constants you can use in setting this action are listed in the table below. Constant PROCEED_DO_NEXT_STEP Explanation Continue with the next step. For example, if the handler-information object s mproceed variable is set to PROCEED_DO_NEXT_STEP in a prebind routine, the next step to be performed will be the binding step. 226

248 Chapter 8: Data-Agent Programming Constant PROCEED_SKIP_NEXT_STEP PROCEED_DO_SUCCESS_PAGE PROCEED_DO_FAILURE_PAGE Explanation Skip the next step. For example, if the handler-information object s mproceed variable is set to PROCEED_SKIP_NEXT_STEP in a prebind routine, the next step to be performed will be the execute-action step. Go directly to the success routine. Go directly to the failure routine. Note - In HAHTtalk Basic project, you should prepend DMConstants_ to the names of these constants. The upcoming section Example of changing the flow of control, illustrates how to set the mproceed variable to one of these constants. Example of changing the flow of control Here s a simple example of how to change the flow of control in a command handler. Say that you have a prebind routine, like the one discussed in Customizing a failure page on page 223, that records error information in a user property of a Request object if an error occurs. For instance, the prebind routine in that example can fail if the routine is unable to find the file it is supposed to read. At this point, you should not only record your error information, but tell the command handler to go directly to its failure routine. The code below illustrates how to do this. Java try { picturestream = new FileInputStream (picturefile); } catch (java.io.filenotfoundexception e) { arequest.setuserprop("errormessage","file not found!"); ahandlerinfo.setproceedaction (DMConstants.PROCEED_DO_FAILURE_PAGE); return; } 227

249 Chapter 8: Data-Agent Programming Note that the variable mproceed is set using the DMHandlerInfo object s setproceedaction method. 228

250 Programming with the Connection Manager 9 The DMConnectionManager class Opening a connection Opening a shared connection Opening a private connection Closing a connection Connections in HAHTtalk Basic projects

251 Chapter 9: Programming with the Connection Manager The DMConnectionManager class The HAHTsite Server Object Model includes a connection-manager class named DMConnectionManager. This class includes methods that enable you to open or obtain a reference to a shared connection and to open a private connection. Once you obtain a Connection, you can use it in your ADO programming as you normally would. For example, you might instantiate a Recordset and then set the recordset s active connection using your Connection object. A shared connection can be opened by a session the first time the connection is needed and then be used for the duration of the session by both your code and any number of data agents. Sharing a connection improves an application s performance because you avoid the overhead of opening multiple connections. Some applications may require or prefer to use private connections, however. For example, an application that performs transactions might choose to conduct those transactions over a private connection. You might be thinking, ADO allows me to create connections of different scopes, so why would I use the connection manager? There are two main reasons: The management of connection strings is simplified. If you need to change a connection string, you can make the change in one place the definition of the connection and all of the code pages that might open the connection will know about the new connection string. You can share a connection with one or more data agents. A data agent uses the DMConnectionManager class to open a shared connection to a data source, and you can use a method of this class to get a reference to the same connection. The remainder of this chapter discusses the procedures for opening and closing shared and private connections using the DMConnectionManager class. Opening a connection The general procedure for opening a connection or getting a reference to a shared connection is as follows: 1 Create an ADO connection using the HAHTsite IDE. The procedure for creating this connection is covered in Chapter 15, Connecting to a Data Source, in the HAHTsite IDE and IP User s Guide. 230

252 Chapter 9: Programming with the Connection Manager 2 If the user will be getting a reference to a shared connection and the connection s data source requires that the user log in, set up a login page that user must visit before getting the shared connection. The name of this login page is an attribute of the connection. 3 Call the appropriate SOM method to open or get a reference to the connection. The subsections below explain in detail how to call the proper method to establish a shared or private connection. Opening a shared connection Generally, you get a reference to a shared connection using the method getsharedconnectionbyname: com.haht.ado.abstract.connection getsharedconnectionbyname (String connname) The single argument to this method is the name of an ADO connection created in the IDE. Note - You can also get a reference to a shared connection using the method getsharedconnectionbyid. Using this method, however, makes your code a little harder to read since it requires the project ID of a connection as its argument. This method is primarily for use by data agents. Before you call the getsharedconnectionbyname method, you should determine whether the connection s data source requires that users log in. If users must log in, your application must include a data agent that establishes the shared connection before your code attempts to get a reference to that connection. Also, the definition of the connection itself must include the name of a login page that will enable users to log in to the data source. The call to getsharedconnectionbyname will return null if: the connection required a login and the user has not logged in yet a connection of the name you supplied does not exist Java programmers: The getsharedconnectionbyname method can throw two exceptions: SharedConnectionUnpreparedException and UnknownConnectionException. This means that you should make this call using the try/catch mechanism. The first exception indicates that the connection s data source requires a login and that the user has not logged in, and the second exception indicates that the application does not know of a connection with the name you specified. 231

253 Chapter 9: Programming with the Connection Manager Opening a private connection Generally, you open a private connection using the method openprivateconnectionbyname: com.haht.ado.abstract.connection openprivateconnectionbyname (String connname, String userid, String password) The three arguments to this method are: the name of an ADO connection created in the IDE a user ID to be used in logging in to the data source a password to be used in logging in to the data source Use empty strings for the second and third arguments if the connection s data source does not require that users log in. Note - You can also open a private connection using the method openprivateconnectionbyid. Using this method, however, makes your code a little harder to read since it requires the project ID of a connection as its argument. This method is primarily for use by data agents. The call to openprivateconnectionbyname will return null if: the method is unable to log in to the connection s data source a connection of the name you supplied does not exist Java programmers: The openprivateconnectionbyname method can throw two exceptions: PrivateConnectionUnpreparedException and UnknownConnectionException. This means that you should make this call using the try/catch mechanism. The first exception indicates that the connection s data source requires a login and that the method was unable to log the user in, and the second exception indicates that the application does not know of a connection with the name you specified. Closing a connection Because you might want to open and close a private connection repeatedly during a session for example, you might want to open and close the connection each time you access a data source HAHTsite provides a method that enables you to close a private connection explicitly: void closeprivateconnection(com.haht.ado.abstract.connection) 232

254 Chapter 9: Programming with the Connection Manager If you don t call this method, HAHTsite closes all private connections when a session ends. Similarly, HAHTsite closes all shared connections automatically when a session ends. Connections in HAHTtalk Basic projects Because most HAHTtalk Basic programmers would prefer to work with connection objects of type ADODB.Connection rather than objects of type com.haht.ado.connection, HAHTsite includes four Basic functions that return connections: getsharedconnectionbyid getsharedconnectionbyname openprivateconnectionbyid openprivateconnectionbyname These functions serve the same general purpose as their Server Object Model counterparts, but return connections of type ADODB.Connection. In addition, the class ADODB.Connection defines a closeprivateconnection method that you can use to close private connections. 233

255 Chapter 9: Programming with the Connection Manager 234

256 Working with Client-side Scripts 10 Introduction to client-side scripts Types of client-side scripts Choosing a scripting language Client-side scripts and the HTML editor Writing in-line scripts Writing script functions About event handlers Browser compatibility issues About Dynamic HTML Scripts with server-side expressions

257 Chapter 10: Working with Client-side Scripts Introduction to client-side scripts Client-side scripts enable you to include executable content in Web pages, providing dynamically created HTML content, interaction with the user, and control of the Web browser. You can use client-side scripts in a variety of ways. Some of the common uses are: to validate form fields before submitting a form to animate menus to indicate mouseovers to display a special picture, depending on the user s history to enforce an ordered navigation of a set of Web pages to interact with and control the execution of applets As a simple example of what you can do with client-side scripts, try entering the following text into a page using the Normal view of the HTML editor: The Fibonacci sequence document.write("1, 1"); first = 1; second = 1; for(i=0; i<100; i++) { third = first + second; first = second; second = third; document.write(", " + third); } Select the lines of JavaScript code (everything except the first line), and click the Client-side script button. When you view the page in a browser, you will see the following output: 236

258 Chapter 10: Working with Client-side Scripts The JavaScript code that you place on a Web page is interpreted by the browser, which dynamically generates the HTML content that is displayed. Using client-side scripts allows you to run programs on a viewer s computer within the Web browser. The HAHTsite IDE/IP includes a rich script-aware HTML editor for writing, testing, and debugging client-side scripts in a Web page. The HTML editor supports both JavaScript and VBScript as scripting languages. In addition, the Document Object Models (DOM) for the major Web browsers are incorporated into the editor, allowing drag-and-drop insertion of objects, properties, and methods from the DOM directly into the scripts. This is a very powerful feature that simplifies the complex task of writing scripts using objects in the browser s DOM. Perhaps the most difficult task associated with writing client-side scripts is dealing with incompatibilities in the different versions of Netscape Navigator and Internet Explorer. The HTML editor filters the DOM presented in the editor, supporting writing scripts for targeted browsers. This chapter explains how to use the HTML editor to create Web pages with scripts. The reader is assumed to understand JavaScript or VBScript and the concepts involved in using the DOM for the target browser. Because of the predominate use of JavaScript, the examples in this chapter use JavaScript. However, the use of the HTML editor is the same, regardless of the scripting language. 237

259 Chapter 10: Working with Client-side Scripts Types of client-side scripts When you re using its Normal view, the IDE s HTML editor acts as a WYSIWYG Web page editor. When used in this mode, the editor has features that enable you to add client-side scripts to a Web page. In addition, the editor has a Client Scripts view that you can use to create event handlers and functions for your scripts. The HTML editor supports three basic types of scripts in a page: in-line scripts. The HTML editor allows you to type script statements directly into a Web page, at the place that the browser should execute the script. These in-line scripts appear in the Normal view of the HTML editor and are marked with a special font. Writing in-line scripts is explained in Writing in-line scripts on page 243. page-scope functions. You can write script functions to perform common functions or to improve readability. Page-scope functions are created in the Client Scripts view of the HTML editor and are available to in-line scripts or event handlers anywhere on the page. These functions are not visible in the Normal view. If you put the bulk of your scripting code into functions, Web pages with in-line code maintain a more WYSIWYG look because they have fewer in-line statements. Creating page-scope functions is discussed in Writing script functions on page 244. event handlers. The Client Scripts view of the HTML editor provides a convenient way to write event handlers associated with an event for an object on the page. The scripts for each event are created and edited in the Client Scripts view, and are not shown on the page in the Normal view. More information about writing event handlers is provided in Scripting event handlers on page 247. Choosing a scripting language The HTML editor supports the use of both JavaScript and VBScript in client-side scripts. Both languages provide basic control flow and support for creating Web pages that are customized at display time. However, JavaScript is recognized by more browsers and is more widely used than VBScript. The most important difference between JavaScript and VBScript is browser support. JavaScript is supported by Navigator and IE. VBScript is only supported by IE. If you use VBScript, only clients that are using IE will be able to correctly view your pages with scripts. Scripting-language and 238

260 Chapter 10: Working with Client-side Scripts browser-compatibility issues are discussed further in Browser compatibility issues on page 249. You can choose to use either JavaScript or VBScript as the current scripting language. If you intend to use only one language for all your scripts, you can make this choice once using an HTML editor option, and all the scripts that you write will be generated in that language. If you need to write in both JavaScript and VBScript, you must change this setting each time you edit a different type of script. To select the current scripting language 1 From the main menu, select Tools > Options... The Options dialog appears. 2 Select the Client Scripts tab. 3 From the Default Client Script LANGUAGE combo box, select either JavaScript or VBScript. You can also type an entry into this field to specify a different scripting language or a specific version of a language, such as JavaScript Click OK. The script language you select will be used by the HTML editor for any new scripts that are created. 239

261 Chapter 10: Working with Client-side Scripts Client-side scripts and the HTML editor When an HTML page is opened in a project, it is first displayed using the Normal view of the HTML editor. The Normal view displays an editing window with a WYSIWYG representation of the page. While you re in this view, client-side scripts appear as in-line code, or as icons, depending on the setting of the View Code as Icon option. When you switch to the Client Scripts view, the DOM Objects tab is selected in the Project window. The DOM Objects panel contains a graph representation of the client-side script tags and client-side objects. The objects and tags are placed in a hierarchy represented by folders. The editing window contains the currently selected script. The DOM Objects window only displays the object model when the HTML editor is in the Client Scripts view. Note - There are no real folders corresponding to this representation. The folders are only used as a convenient mechanism for presenting the tags and objects in an easy-to-use way. The Client-Side Script Tags folder lists both functions and in-line scripts contained in the page. The first script in the list of Client-Side Script Tags is used to create page-scope functions. Page-scope functions are discussed in Writing script functions on page 244. Any other functions or in-line scripts in a page will also appear as script elements in this list. The script that is currently being edited is signified by a red highlight box around the script s icon. In the illustration above, the first script item, which contains the page scope functions, is being edited. When you switch between Normal and Client Scripts view, if possible, the HTML editor maintains the focus on the item currently being edited. For instance, if you are editing (or place the cursor in) an in-line function while in Normal view, then switch to the Client Scripts view, the script containing that function will be automatically selected for editing. 240

262 Chapter 10: Working with Client-side Scripts Tip - If you are not sure which in-line script or function a particular script in the list of Client-Side Script Tags represents, select the script for editing and switch back to the Normal view of the editor. The script you have selected will be the currently selected object. Browsing the object model Client-Side DOM Objects represent objects in the browser object model. The Client-Side DOM Objects graph has two root level objects, window and navigator. The window object represents the Web browser window or a frame within a window. All page-scope variables belong to this object. The document object, contained in the window object, represents the document associated with the window. By traversing the hierarchy, you can see the objects, events, properties, and methods that define the object model. The following types of items appear in the DOM Objects panel: icon item objects - the forms, buttons, text boxes, or even the document arrays - items of the same type (e.g., scripts, forms, frames, images) properties - object attributes functions - object functions events - event handler scripts can be associated with these events In addition to icons representing the type of item, you will notice that some items have a browser indicator on the icon. These additional indicators mark items that are only defined in Navigator 4.x or IE 4.x, or both. The browser indicator may appear on icons for objects, properties, functions, and events. No browser symbol on the item indicates that the feature is supported by all of the browsers (or at least the third generation browsers.) icon Browsers supported Most browsers support these objects, properties, functions, or events. Navigator 4.x only 241

263 Chapter 10: Working with Client-side Scripts icon Browsers supported IE 4.x only Navigator 4.x and IE 4.x only (not supported in earlier versions of the browsers) Note - When you re browsing the DOM Object panel, the script currently being edited may not always be visible. Remember that the icon for the script being edited in the editing window is indicated by a red highlight box. Configuring the Client Scripts view The DOM Objects window of the Client Scripts view of the editor can be configured to display as much or as little information as you would like to see. Instead of displaying all of the objects supported by all of the browsers, you can display just the objects supported by specific browsers. To configure the DOM Objects panel 1 From the main toolbar, select Tools > Options... The Options dialog appears. 2 Click on the Client Scripts panel of the Options dialog. 3 Configure the panel to display the information you wish to see. 242

264 Chapter 10: Working with Client-side Scripts Field Display Properties and Methods Default Client Script LANGUAGE Display Objects for Browsers Description If checked, show the events, properties, and functions associated with each object. If not checked, only show the events associated with an object. Select the scripting language from the drop-down menu. New event handlers or scripts that you add will use this value. Select the browser for which to show the object model from the drop-down menu. <all> displays all objects and object features supported by any browser in this list. Selecting a browser from this list filters the object model so that only objects and features supported by that browser appear in the DOM Objects panel. 4 Click OK. Note - Selecting a particular browser s object model to be displayed in the Client Scripts view does not prevent you from writing scripts that are incompatible with the browser. This selection only affects the object model that is shown. There is no testing for browser compatibility in the editor. Writing in-line scripts You can add scripts in-line on a page while you re in the Normal view. These scripts will be visible in the HTML editor, but will not be visible on the page when viewed by a browser. Script statements and functions are executed in order as they are read from the page by the browser. To insert script statements into a page 1 With the page open in the Normal view, place the cursor at the location at which you want to enter the script. 2 Type in the script statements. Note - The IDE/IP does not check for errors in any scripts. Errors in scripts will not be seen until the page is displayed in a browser, so it is a good idea to test your pages thoroughly. 243

265 Chapter 10: Working with Client-side Scripts 3 Select the script statements. 4 Click the Client-side script button on the Character Styles toolbar. The script appears in a special font and color. The figure below shows a simple JavaScript example that conditionally displays information in the Web page based on the month. When a browser receives this page, it interprets the JavaScript code and, based on the current month, replaces the JavaScript code with the appropriate HTML output. Tip - If you want to hide in-line scripts, select View > Code As Icon from the main toolbar. The scripts on the page will be replaced with the client-side script icon. Once you ve created an in-line script in the Normal view, you can edit it in the Client Scripts view of the HTML editor. Editing scripts in the Client Scripts view gives you access to the object model displayed on the DOM Objects tab in the Projects window. Writing script functions You use the Client Scripts view of the HTML editor to create script functions with page scope. Functions are subroutines that can be called either by in-line script statements on the page or from event-handler scripts. The visibility or scope of a function is determined by its position on a page. A function is visible to any script statement that occurs after the function definition on the page. A function has page scope if it is visible to statements anywhere on the page. The HTML editor defines a General script for each page containing functions that have page scope. 244

266 Chapter 10: Working with Client-side Scripts A common practice is to place code that is called from multiple places on a page into a function. Functions may also be used to keep the number of in-line statements inserted into a page small. This will make the page more readable. To insert a script function into a page 1 Open the page and select View > Client Scripts from the main toolbar. Shortcut - Use the buttons on the Change Active View toolbar to switch between views in the HTML editor. 2 Click on the script icon to select the first script in the Client-Side Script Tags list. A script for page scope functions appears in the editing window. If the page has scripts in the <HEAD> tag, this is the first script that appears in the <HEAD> tag. A page can have multiple scripts in the <HEAD> tag. Each script appears as a separate icon under the scripts folder. If the <HEAD> tag does not contain any scripts, a General script is generated. The first line in the General script initially contains the comment line: // General SCRIPT tag in HEAD tag. Put page scope client script // functions here. 3 Type in script functions and variables definitions that require page scope. To try this out, create the print_todays_date function shown below: function print_todays_date() { var d = new Date(); document.write(d.tolocalestring); } 4 Switch back to Normal view and insert a call to the function on the page where you want the date to appear. print_todays_date(); 5 Select the line containing the function call and click on the Client-side script button. 245

267 Chapter 10: Working with Client-side Scripts When you browse the page, the date will appear in place of the function call. You can also insert functions in-line in a page. These functions will only be visible to scripts occurring after the function definition on the page. These functions will be visible in the Normal view and also in the DOM Objects window in the Client Scripts view of the HTML editor. If a function is used by multiple pages, you might prefer to keep the function in a separate file in the project and include it in each script that uses the function. A function that pops up a dialog to ask Are you sure? might be used on several different pages. If a script includes this function, it only has to be changed in one place if you what to change this popup. Shortcut - While editing the page in Normal view, drag-and-drop the script file from the Project window onto the page. This will insert a reference to the script file as a page-scope function. HTML tags for client-side scripts The HTML editor generates the HTML <SCRIPT> tags that contain the scripts in the page. If you look at the page in HTML Tags view, you will see individual script tags for each in-line function and set of statements on your page. When script statements or functions are inserted in-line using the Normal view, the <SCRIPT> tags are generated to include the statements at the location in the body of the HTML where the code appears. Page scope functions, including references to script files containing functions, are inserted in the <HEAD> tag. These scripts are placed in the <HEAD> tag so that the functions are defined 246

268 Chapter 10: Working with Client-side Scripts before any other scripts on the page. Event-handler scripts are inserted in the tag for the object associated with the event. Although the HTML editor provides a very flexible way to insert client-side scripts into a HTML page, there may be occasions where you will need to edit the HTML tags for the scripts directly. The HTML Tags view of the HTML editor provides a convenient way to do this. About event handlers Most browsers in use today have defined a set of objects that represent the browser and the page that it displays. These objects are commonly referred to as the Document Object Model or DOM. (The browser object model is discussed more fully in The browser object model on page 250.) The user interacts with these browser objects by performing actions such as moving a cursor over a link, pressing a button in a form, clicking in a frame, or loading a document in a window. These actions are called events. By creating scripts that run when one of these events occur, you can enable user interaction with the page and control some browser behavior. An event handler is a script that the browser invokes when a particular event, such as a mouseover, occurs. For instance, you could write a script that displays a different picture when the mouse is held over a picture. The HTML editor provides an easy way to generate these scripts by allowing you to browse a hierarchical representation of all of the available objects and their associated events, select an event to bind to a script, and create the script for that event. A powerful feature of the HTML editor is the encapsulation of the object models for all of the commonly used browsers. By selecting the browser(s) that you want to support in your scripts, you can view the objects and their associated methods, properties, and events. You can even use drag-and-drop to insert the code for accessing the object model into your scripts. Scripting event handlers Using the browser s object model, as presented in the DOM Objects window of the Client Scripts view, you can identify the event that you want to associate with an event-handler script. Browsing the object model on page 241 explains how the objects are organized in the DOM Objects window. While creating the script, you can also use the DOM Objects view to locate and insert the code to access properties and functions of any object that is available on the page. Complete documentation of the object models is outside the scope 247

269 Chapter 10: Working with Client-side Scripts of this document. Up-to-date documentation of the object model is available online from the Web browser vendors. There are also many reference books with extensive coverage of the use of the object models. To write an event handler script 1 In the Client Scripts view of the HTML editor, click on the icon of the event to be associated with the script. The icon for the event will be highlighted with a red box. The editing window now contains the script currently associated with this event. If there is no script currently associated with this event, the editing window will be empty. Shortcut - In the Normal view of the HTML editor, select the object with which the script should be associated. Switch to the Client Scripts view. The DOM Objects panel now indicates that the currently selected item is an event associated with this object. The HTML editor maintains focus on selected objects and events when switching between views. 2 In the edit window, enter the script code for the event. The browser will execute this code when the event occurs. 3 To insert the code to reference a property or method from the object model into the script, drag-and-drop the icon for the property or method from the DOM Objects panel into the editing panel. Note - Event handling scripts do not appear in the Normal view of the HTML editor. 248

270 Browser compatibility issues Chapter 10: Working with Client-side Scripts Perhaps the most difficult part of developing Web content is dealing with browser compatibility issues. This is especially true when developing client-side scripts. Aside from differences in features, you must consider which browsers and platforms the viewers of the Web page will be using. When writing client-side scripts you need to be aware of: the scripting language and version (JavaScript or VBScript) the browser type and version (Navigator, IE, others) the OS platform and version (Windows, Mac or UNIX) JavaScript is the predominate scripting language used today. Different browsers support different versions of JavaScript. The table below shows the language level support of the two major browsers. Script Language Navigator Internet Explorer VBScript IE JavaScript 1.0 Navigator 2.x IE 3.x JavaScript 1.1 Navigator 3.x JavaScript 1.2 Navigator 4.x 1 IE 4.x 1. Not fully compliant If you specify JavaScript in the Client Scripts tab of the Options dialog, any browser that supports JavaScript1.0 or later versions will be able to run your scripts. The IDE/IP generates JavaScript code that will only be executed by browsers that understand the script tag and that have script capabilities turned on. The different versions of JavaScript reflect changes in the core language, such as support for arrays, strings, and Java scripting. The objects in the DOM Objects window of the Client Scripts view are not part of the JavaScript language and are not determined by the version of JavaScript used, but by the browser s object model. The greatest difference in browser compatibility is in the Document Object Model or DOM, and support for Dynamic HTML. The DOM continues to evolve with each version of the browsers. In Navigator 4.x and IE 4.x, there was a significant divergence in the DOM. As a result, there has been a push for a common DOM standard that may result in a common base for writing 249

271 Chapter 10: Working with Client-side Scripts client-side scripts in the future. Currently, you have to make some strategic decisions about which browsers and feature sets to support. The browser object model Both Navigator and IE have defined object models that provide a programming interface to control the content and behavior of the displayed Web pages. These object models are sometimes referred to as the Document Object Model, or DOM. Two very important objects in the DOM are the window object and the document object. The window object is a root-level object that represents the window that the browser uses to display a Web page. Some of the objects that can be accessed from the window object are: frames contained in the window a document (or Web page) loaded into the window colors used in drawing items in the window the URL for the document The document object, which is subordinate to the window object, represents the HTML page. Some of the objects accessible from the document include: images and applets displayed on the page forms and elements in the forms (text boxes, buttons, radio buttons, etc.) links and anchors in the page cookies Objects have properties or attributes that can be queried and sometimes set by scripts. Many objects also have functions, which are methods that scripts can invoke to cause the object to take some action. Many objects also have events triggered by the browser as the user interacts with the page. Events are particularly useful for enabling user interaction. When an event occurs, such as the user clicking on a button, the browser invokes the event handler script associated with that event. Strategies for handling browser incompatibilities The HTML editor gives you the ability to filter out objects, properties, and events in the graph of objects in the Client Scripts view. You can choose to browse through all of the possible features, or display a subset of the DOM containing only those objects, properties, and methods supported by a specific browser version. In addition, if you right-click on an object in the DOM and 250

272 Chapter 10: Working with Client-side Scripts select Properties..., a Document Object Properties dialog lists the browsers that support that object. Here are a few strategies for addressing browser compatibility: least common denominator. If you use only the language features and DOM supported by Navigator 2.x, your scripts will run on all of the browsers currently in use. The level of sophistication possible at this level is fairly low. The only dynamic content supported is forms, form fields, and links. By moving the bar up to Navigator 3.x, you still retain a majority of the browsers in use and gain some additional capabilities, such as dynamic images and the ability to script Java applets. conditional coding. Write your scripts to determine the browser at runtime, and run scripts that have been written for that browser version. You may choose to interleave browser specific code in the page. Supporting multiple browsers is a lot of work, but it lets you present the best appearance possible to all viewers. ignore the problem. Maybe you do not have to write scripts that can be viewed by everyone. If so, write for the browser version of your choice and fail gracefully on the rest. Consider yourself very lucky. Platform specific compatibilities are difficult to anticipate. The basic premise is that the scripting languages and browser support allow Web content including scripts to be platform independent. In practice, implementations are not perfect and there are incompatibilities and as well as bugs that may cause users to experience difficulty viewing your page. Internet sources such as user groups and FAQs are your best source for this type of information. The following example JavaScript code takes advantage of a feature that is only present in IE 4.x. var browser = navigator.appname; var version = parseint(navigator.appversion); var bisie4 = (browser.indexof("microsoft")!= -1) && (version == 4); // if this is running on IE 4, scroll the form to the top of the // window if ( bisie4 ) { document.form2.scrollintoview(); } Although the LANGUAGE attribute of the <SCRIPT> tag could be used to prevent browsers from running scripts that include features of later versions of the language than the browser supports, it is preferable to query the 251

273 Chapter 10: Working with Client-side Scripts Window.navigator object to conditionally execute code targeted for specific browsers. About Dynamic HTML Navigator 4.x and IE 4.x introduced greatly enhanced support for Dynamic HTML (DHTML). In addition to a richer DOM, DHTML has an extended event model and support for absolute positioning though cascading style sheets (CSS). Unfortunately, the DOM s properties used by the fourth generation of Navigator and IE to position elements are very different. To access the object properties, you have to use browser sensing. The next generation of browsers may become more compatible as the standards for a common DOM are adopted. In spite of the current difficulties, DHTML offers the option of creating truly interactive, dynamic Web pages. The HTML editor enables you to develop DHTML for both Navigator and IE browsers by providing the complete DOM for both browsers and the ability to drag-and-drop code for object references as well as an intuitive interface for binding scripts to events. Dynamic positioning of elements is done through layers in Navigator and CSS properties in IE. Both of these methods are supported in the HTML editor as part of the object model for the browser. Moving objects using DTHML Here s a simple example that illustrates how to use DHTML in HAHTsite to animate objects. Say that you want a picture to change its location in a window when the user clicks a button. This example shows how client scripts can detect browser types, and move an object using CSS positioning for IE 4.x browsers and Netscape Layers for Navigator 4.x browsers. 252

274 Chapter 10: Working with Client-side Scripts This example involves the following steps: 1 Insert a picture and a set of buttons to control the movement of the picture on a page. 2 Create a Netscape Layer. This task is described in To create a Netscape Layer from a SPAN on page Add client scripts to the buttons that move the object, using browser specific mechanisms for positioning the objects. Why use Netscape Layers for positioning? In IE 4.x browsers, CSS positioning can be used to position any object in the document. Navigator 4.x does not support CSS positioning directly for all document objects. In Navigator 4.x positioning of objects is enabled by embedding the objects in Netscape Layers, which can be moved through positioning. Before an object like a picture can be moved, the picture needs to be inserted into a <SPAN> tag which can be turned into a layer. Only container objects like <SPAN> and <DIV> can be treated as layers. To create a Netscape Layer from a SPAN 1 In the Normal view of the HTML editor, select the object(s) to be inserted into a layer. For example, to insert a picture, click on the picture. 2 From the main toolbar, select Insert > Span... The Insert SPAN dialog appears. 253

275 Chapter 10: Working with Client-side Scripts 3 Click on the Properties... button to set the Style property. The Style Properties Page Editor appears. For more information about setting these properties, see Chapter 12, Cascading Style Sheets, in the HAHTsite IDE and IP User s Guide. 4 Select the Positioning tab of the Style Properties editor. 5 Set the Position to relative. Setting the Position attribute of the Style Properties to relative or absolute makes the SPAN into a Netscape Layer. 6 Click OK. 7 Type a value for the SPAN tag into the ID field of the Insert Span dialog. 8 Click OK. 254

276 Chapter 10: Working with Client-side Scripts JavaScript example for browser-independent DHTML As a result of creating a Netscape layer from the SPAN object, there are two representations of the SPAN object, depending on which browser DOM you are using: The IE 4.x DOM represents the SPAN object as window.document.all.span1. The Navigator 4.x DOM represents the SPAN object as window.document.layers.span1. The DOM Objects window shows the different representations of the SPAN object. To reference these objects in client-side scripts, you must use syntax specific to the object model. The following script is a JavaScript script that is bound to the onclick event of the button labeled Up in the example. When the user clicks on the Up button, the image will move up 10 pixels. JavaScript attached to the Up button if (bisns4) { moveelement(document.span1, 0, -10); } else if (bisie4) { moveelement(document.all["span1"], 0, -10); } 255

277 Chapter 10: Working with Client-side Scripts This example script uses two JavaScript code pages, BrowserVersion.js and MoveObject.js. The first file, BrowserVersion.js, sets the page scope variables bisns4 (browser is Navigator4) and bisie4 (browser is IE4), which are used to determine which DOM will be used. The second file, MoveObject.js, contains the function moveelement() that moves the object on the page. BrowserVersion.js var sagent = navigator.useragent; var bis95nt = sagent.indexof("windows 95") > -1 sagent.indexof( "Windows NT") > -1 sagent.indexof("win32") > -1; var bisie4 = sagent.indexof("ie 4")!= -1; var appver = navigator.appversion; var bisns = (navigator.appname == 'Netscape'); var bisns4 = bisns && (appver.indexof('4')!= -1); 256

278 Chapter 10: Working with Client-side Scripts MoveObject.js function moveelement( element, x, y, animate ) { if ( bisns4 ) { if ( element ) element.moveby( x, y ); else alert( "MoveObject error: element is not a layer. Make sure STYLE=\"position:relative\" is set." ); } else if ( bisie4 ) { if ( element.style.position == "" ) element.style.position = "relative"; sleft = element.style.left.substr( 0, element.style.left. indexof( px )); if ( isnan( parseint( sleft ))) sleft = "0"; element.style.left = parseint( sleft ) + x; } stop = element.style.top.substr( 0, element.style.top. indexof( px )); if ( isnan( parseint( stop ))) stop = "0"; element.style.top = parseint( stop ) + y; } return; These functions could be included as project files that are referenced as page functions or as script functions that are part of the HTML page. See Writing script functions on page 244 for more information on how to include page scope functions in your page. Scripts with server-side expressions You can use information from your application on the server in your client-side scripts by using embedded server-side expressions. In a HAHTtalk 257

279 Chapter 10: Working with Client-side Scripts project, HAHTtalk Basic expressions can be embedded in client-side scripts. In a similar manner, Java projects allow server-side Java expressions to be embedded in client-side scripts. Inserting server-side expressions into a page causes that page to become a dynamic page. When a page containing scripts with embedded server-side expressions is requested by a browser, the Application Server executes the HAHTtalk or Java code and places evaluated expressions into the script before sending the page to the user s browser. The server-side expressions are evaluated by the Application Server each time the page is requested by a browser. Embedded server-side expressions are marked using the following a begin-and-end syntax: /*== marks the beginning of a server-side expression */ marks the end of a server-side expression For example, the following code initializes the JavaScript variables pagesvisited and username to values stored in the HAHTtalk Basic variables PagesVisited and LoginUser: var pagesvisited = /*== PagesVisited */; var username = '/*== LoginUser */'; When the page containing this code is requested, the Application Server evaluates the HAHTtalk Basic expressions and sends the following script to the browser: var pagesvisited = 10; var username = 'Zachary'; Note the single quotes around /*== LoginUser */. These quotes are required because LoginUser is a string variable. When string variables are evaluated, they need to be in quotes. The server-side Java expression equivalent to the above HAHTtalk Basic example would be: var pagesvisited = /*== com.haht.project.pagesvisited */; var username = '/*== com.haht.project.session.getusername()*/': 258

280 Using HtmlOut Routines or the HtmlOut Class 11 Creating HTML at runtime The HAHTtalk Basic HtmlOut library Using the HAHTtalk Basic HtmlOut library HAHTtalk Basic example The HtmlOut Java class Java example

281 Chapter 11: Using HtmlOut Routines or the HtmlOut Class Creating HTML at runtime You may have situations in your applications where you want to build HTML tags on-the-fly (at runtime). For example, dynamic pages often contain information that has been retrieved from a database system or from another software system. Both HAHTtalk Basic and Java provide database access using ODBC and support ActiveX, OLE automation, DLL calls, and other mechanisms for communicating with other software systems. Once you receive information from one of these systems, you must format the data and display it on a dynamic page. For example, you may want to retrieve the records from a database and display the data in an HTML table. To accomplish this, you need to generate HTML table tags at runtime. In most cases, you ll use HAHTsite s wizards and widgets to display the database data. However, there may be cases where you want to format data in special ways not supported by a wizard or widget. You can generate HTML tags with HAHTtalk Basic print statements or with Java calls to out.print() or out.println(). For example, the following HAHTtalk Basic print statement displays the value of the LastName variable in the cell of an HTML table: Print "<TD>" & LastName & "</TD>" You certainly wouldn t want to write print statements each time that you want to create some dynamic HTML. Fortunately, HAHTsite includes both a library of HAHTtalk Basic HTML routines and a Java class, both called HtmlOut. The HAHTtalk Basic HtmlOut library The routines and their arguments are documented in the HtmlOut.hbs file, which is installed in HAHTsiteInstallDir\scripts (where HAHTsiteInstallDir is the directory into which HAHTsite was installed; C:\HAHTSITE, for example). In addition to this source file, the HAHTsiteInstallDir\include directory contains the file HtmlOutDecl.hbh, an include file that contains the declarations for the HtmlOut routines. The HtmlOut library contains general-purpose routines that generate HTML tags. For example, you would use the htmltabledatatext routine to print the value of LastName in a cell of an HTML table: htmltabledatatext LastName,0,0,0 260

282 Chapter 11: Using HtmlOut Routines or the HtmlOut Class The 0,0,0 arguments represent additional HTML parameters (alignment, column spanning, and row spanning) that aren t used in this example. The HtmlOut routines include support for: line, paragraph, indenting, and ruler tags character formatting lists and numbered bullets links and bookmarks images forms and form fields tables frames headers Using the HAHTtalk Basic HtmlOut library To use HAHTtalk Basic HtmlOut routines in your project you have the option of including the library either globally (for all files in your project), or at the page level. Including the HAHTtalk Basic HtmlOut library at the page level 1 Create in the project a code page and copy to it the contents of the HtmlOut.hbs file. For example: Create a code page named HtmlOutInclude.hbs. Copy the contents of the HAHTsiteInstallDir\Scripts\HtmlOut.hbs file into your project s HtmlOutInclude.hbs page. 2 Include the HtmlOut declarations file (HtmlOutDecl.hbh) in each page that uses the HtmlOut routines or in each page of the project. 3 If you are using the HtmlOut routines in only a few pages, you can include the declarations file in the pages. To do that: With the page that will use the HtmlOut routines open in the HTML editor, select View > Server-Side Code to display the page in server-side code view. Scroll to the top of the page to find the Imports and includes section. 261

283 Chapter 11: Using HtmlOut Routines or the HtmlOut Class 4 Type the following #include directive into the Imports and includes area. #Include <HtmlOutDecl.hbh> You can now call the HtmlOut subroutines from this page. Including the HAHTtalk Basic HtmlOut library for all pages in your project 1 If you don t already have a Globals.hbs page in your project, create one. 2 In the Globals.hbs page, place the directive: #Include <HtmlOutDecl.hbh> 3 Call the HtmlOut subroutines from your project s Web pages. HAHTtalk Basic example This example is provided as a way to demonstrate the features of some HAHTtalk Basic HtmlOut routines. Typically, you would build a table, like the one shown in this example, with the Report Wizard. Below is sample code that uses HtmlOut routines to create dynamically the rows of a table, based on how many records are in the Data Set DataSet1. The code displays a three-column table showing a record count, an employee s first name, and last name. 262

284 Chapter 11: Using HtmlOut Routines or the HtmlOut Class HAHTtalk Basic Dim NumFound As Integer, I As Integer Dim MatchingRec As String ' Get the number of records in the Data Set. NumFound = DataSet1_RecordSet.DynaSet.RecordCount ' Print the number of matching records. MatchingRec = " matching records." If NumFound = 1 Then MatchingRec = " matching record." End If Print "Found " & NumFound & MatchingRec ' Start the table. 1=1-pixel border htmltablestart 1,0,true,0,true,0,0 ' Start a row for the column headers. 0=left aligned row. htmltablerowstart 0 ' Print the three column headers. 2=centered. htmltableheadingtext "Record#",2,0,0 htmltableheadingtext "First Name",2,0,0 htmltableheadingtext "Last Name",2,0,0 htmltablerowend ' Go through the Data Set and get records. Create a row for each ' record and print the data for the three columns. For I = 1 to NumFound htmltablerowstart 0 htmltabledatatext format$(i),0,0,0 htmltabledatatext DataSet1_RecordSet.DynaSet.fields("FirstName").value,0,0,0 htmltabledatatext DataSet1_RecordSet.DynaSet.fields("LastName").value,0,0,0 DataSet1_RecordSet.DynaSet.MoveNext htmltablerowend Next I ' End the table. htmltableend Here is what the table looks like in a browser. 263

285 Chapter 11: Using HtmlOut Routines or the HtmlOut Class The HtmlOut Java class The static member variables of the HtmlOut class are used to generate HTML. In the simplest case, you can use them directly (for example, the Bold and HorizontalRule members can be used to generate text between two horizontal rules and surrounded by boldface tags). HtmlOut.HorizontalRule.renderAsHtml(); HtmlOut.Bold.text("Hello"); 264

286 Chapter 11: Using HtmlOut Routines or the HtmlOut Class HtmlOut.HorizontalRule.renderAsHtml(); or, equivalently: HtmlOut.HorizontalRule.renderAsHtml(); HtmlOut.Bold.start(); // somehow emit the string "Hello" HtmlOut.Bold.end(); HtmlOut.HorizontalRule.renderAsHtml(); HtmlOut class members can also be used as the starting point for more elaborate formatting control (e.g., the FontUp1 member variable creates the HTML <FONT> tag that increases the font size by one step). Red text in this font size can be also be produced as follows: PairedTag myfont = HtmlOut.FontUp1.clone(); myfont.setattribute( "COLOR", "RED" ); myfont.text("hello"); HtmlOut also contains static member functions for creating the HTML tag objects for tables, forms, and other more complex HTML entities. Thus, the example above could also be coded as follows: PairedTag myfont = HtmlOut.makeFont( "", "+1", "RED" ); myfont.text("hello"); Here, the call to makefont creates a font object using the default font face, a font size one step larger, and with the color "RED". Certain arguments of the static member functions are specified as being optional. An optional String argument may be null or the empty string; an optional integer argument may be a negative number. These values cause the attribute in question not to be specified in the HTML, so that the browser will supply its default behavior as shown in the following sample lines of code: PairedTag myfont = HtmlOut.makeFont( "", "", "RED" ); myfont.text( "Hello" ); causes the string Hello to be printed in red in the current font, while PairedTag myfont = HtmlOut.makeFont( "Arial", "1", "RED" ); myfont.text( "Hello" ); causes the string Hello to be printed in red in Arial font. Java example The following is a simple example using the Java HtmlOut class to build and populate a simple HTML table. 265

287 Chapter 11: Using HtmlOut Routines or the HtmlOut Class Java PairedTag mytable = HtmlOut.makeTable(true, 6, 216, false, 99, true, 0, 0,""); PairedTag mytableheader = HtmlOut.makeTableData("CENTER",1,1,"lightblue"); mytable.start(); HtmlOut.TableRow.start(); mytableheader.text("delete Item"); mytableheader.text("material Number"); mytableheader.text("material Description"); mytableheader.text("quantity"); mytableheader.text("net Value"); mytableheader.text("delivery Date"); HtmlOut.TableRow.end(); for(int i=1; i<=3; i++ ) [Need to pick up rowcount from shopping cart object here] { HtmlOut.TableRow.start(); for(int j=1; j<=6; j++) { HtmlOut.TableData.text("Entry in row " + i + " and column " + j); } HtmlOut.TableRow.end(); } mytable.end(); Here is what the table looks like in a browser. 266

288 Chapter 11: Using HtmlOut Routines or the HtmlOut Class 267

289 Chapter 11: Using HtmlOut Routines or the HtmlOut Class 268

290 Access Control 12 What is access control? Granting privileges: the basics Controlling access to a page Controlling access to part of a page Displaying a custom error page Granting privileges to logged-in users Authenticating users with the Login widget Authenticating users with the Authentication interface Letting the Web server authenticate users Granting privileges on a user-name basis Using a Login widget and a database privilege repository Using a Login widget and a nondatabase privilege repository Using the Server Object Model Server Object Model methods

291 Chapter 12: Access Control What is access control? HAHTsite includes a security feature called access control that enables you to restrict a user s access to any pages of your application served by the Application Server. That is, you can protect all dynamic and secure-static pages. Note - Secure-static pages are static pages that you ve chosen to publish to a HAHTsite Application Server either for security reasons or to preserve a state ID. For additional security, you can place your Application Server behind a firewall. The access-control mechanism is based on the concept of privileges. Associated with each dynamic and secure-static page is a set of zero or more required privileges, which are strings that you define. In addition, each user session has associated with it a set of zero or more session privileges. At runtime, the HAHTsite Application Server determines whether a particular user session can access a page by comparing the required page privileges with the session privileges. If all of the page s required privileges are in the session s set of privileges, the Application Server grants the session access to the page. In the figure below, the Application Server will serve the page because the page s required privileges are contained in the user s session privileges. This access-control mechanism is very flexible and has many uses, but here is a simple example of how you could use it. Say that your Web site is a sports-news service, and that some articles are available for free, but others require that users subscribe to your service. You can protect the subscriber-only pages by assigning them the required privilege Subscribed and by initially giving each user session no session privileges. If a user later fills 270

292 Chapter 12: Access Control out a subscription form and submits it, you can assign the user s session the session privilege Subscribed. The user will then be able to read all of the articles on your site. For additional information on implementing this type of security, see Granting privileges: the basics on page 271. This chapter also discusses increasingly complex uses of access control, including: how to have users log in to an application how to assign a set of privileges to users who successfully log in how to assign a user-specific set of privileges to each user who logs in The chapter concludes with some reference material concerning which classes and interfaces in the Server Object Model are useful for implementing access control. Granting privileges: the basics This section explains how to protect a page, or part of a page, from unauthorized access by: assigning a required privilege to a page (or checking for a privilege before displaying a page element) explicitly assigning (or not assigning) one or more session privileges to a user session, using the Session object s addprivilege or addprivileges method The section also discusses how to display a custom error page when a user attempts to access a page that the he or she does not have the privileges to access. Controlling access to a page This chapter s introduction ( What is access control? ) discussed in general terms how a sports-news Web site could control user access to a set of subscriber-only articles. This fictitious site allows general access to some articles, but only subscribers (who have a special session privilege) can access other pages. 271

293 Chapter 12: Access Control How do you initially prevent a user from accessing the subscriber-only articles? And how can you later grant a user session the privilege it needs to access these articles? The following sections answer these questions. To prevent a user from accessing a page 1 Configure the HAHTsite Application Server to enable access control, if necessary. By default, access control is enabled. For detailed instructions on how to perform this task, see Chapter 3, Performing administrative tasks, in the HAHTsite Application Server Administration Guide. Basically, all you need to do, however, is to check an Enable Access Control check box. 2 Add one or more privileges to your HAHTsite project. These become the privileges that you can assign to pages to limit access to them. You add these privileges to a project from the Privileges tab of the Project Properties dialog. For complete instructions on adding privileges to a project, see Chapter 3, Managing Projects, in the HAHTsite IDE and IP User s Guide. The sports-news project has a single project privilege: Subscribed. 272

294 Chapter 12: Access Control 3 Assign one or more required privileges to each protected page. You assign a privilege to a page using the Privileges tab of the Page Properties dialog. For detailed information about assigning a privilege to a page (or other project element), see Chapter 3, Managing Projects, in the HAHTsite IDE and IP User s Guide. In the sports-news project, the subscriber-only pages have been assigned the required privilege Subscribed. Once you ve performed these steps, a protected page is inaccessible to a user who doesn t have the Subscribed session privilege. If such a user clicks a link to a subscriber-only article at the sports-news Web site, the user s browser will display an error page indicating that access to the article has been denied. For information on how to have your application display a more user-friendly error page, see Displaying a custom error page on page 275. To assign a session privilege to a session Have your application call the Session object s addprivilege or addprivileges method. Here s how the sports-news Web site assigns the Subscribed privilege to a session: 1 The application s initial page prompt s the user to follow a link if the user wants to subscribe to the sports-news service. If the user selects this link, the user is taken to a subscription-form page. 2 The user fills out the form and clicks a Submit button. The action associated with the form is to call a subroutine a Java method or a HAHTtalk Basic subroutine. 273

295 Chapter 12: Access Control 3 The subroutine checks the data submitted and, if the data is OK, assigns the Subscribed privilege to the user s session. The code used to assign this privilege is shown below: Java Haht.getSession().addPrivilege("Subscribed"); HAHTtalk Basic HahtSession.addPrivilege "Subscribed" 4 The subroutine also runs the application s initial page. The user can now follow a link to any article. Controlling access to part of a page From the IDE, you can set the required privileges for a page, or for a higher level object such as a folder. However, you might also want to limit access to just one or more elements on a page. As an example, the figures below show two versions of a page requested by a user of the sports-news Web site. The first figure illustrates what a user whose session does not have the Subscribed privilege would see: The figure below shows what a user whose session does have the Subscribed privilege would see: 274

296 Chapter 12: Access Control The conditional elements on a page are controlled by an if statement that determines whether the user s session has a required privilege. Java if (Haht.getSession().hasPrivilege("Subscribed")) { // Conditional elements go here } HAHTtalk Basic If (HahtSession.hasPrivilege("Subscribed")) Then ' Conditional elements go here End If Displaying a custom error page You can create a custom error page for the Application Server to display when a user tries to access a page for which he or she does not have the necessary session privileges. The figure below shows a simple access-denied page. 275

297 Chapter 12: Access Control To create such a page, you: copy a set of error-page templates (supplied with the Application Server) to a directory of your choosing edit the template named HS_access.html so that it contains the content you want to display set the Application Server s Error Page Directory (on the Logging Options page) to the name of the directory that contains the copied templates stop and restart your server group Once you ve performed these steps, the Application Server will display the new error page the next time an access violation occurs. This subject is explained in more detail in Appendix A of the HAHTsite Application Server Administration Guide. Granting privileges to logged-in users Granting privileges: the basics on page 271 explained how to handle the situation where you give a user the privilege to access a protected page when the user visits another page. In particular, that section looked at an application that gives a user a privilege when the user fills out a subscription form. The first time the user visits such a site, the user gets a session privilege by submitting a form, but what about subsequent visits to the site? If the user is assigned a user name and password during the first visit, the site would likely require the user to log in to the application to get his or her privilege on a second or subsequent visit. This section explains how HAHTsite supports assigning users privileges when they log in to an application. There are several ways to handle this situation in HAHTsite: 276

298 Chapter 12: Access Control One way is to use the HAHTsite s Login widget in your application. When a user loads a page containing this widget, the widget displays a page containing a login form, which generally contains user-name, password, and (optionally) Windows NT domain text boxes. When the user fills out and submits this form, the widget attempts to authenticate the user using authentication information maintained by the operating system or in a user-defined location. If the user is authenticated, the widget assigns the user one or more session privileges and calls a success page. If the user is not authenticated, the user does not receive any privileges, and the widget calls a failure page. The Login widget is implemented using calls to Server Object Model methods; therefore, it s possible for you to authenticate users and assign privileges to them by calling these same methods directly. If you want a Web server to authenticate users, you can simply configure your Web server s authentication mechanism appropriately. If a user logs in successfully, your application can assign the user privileges using the Session class s addprivilege or addprivileges method. Authenticating users with the Login widget When you use the Login widget in your application, you can authenticate users against authentication information maintained: by the operating system in another ( user-defined ) location, such as an LDAP directory or a database The procedures for the two types of applications are very similar. The only difference is that HAHTsite includes a Java class that performs operating-system authentication. To authenticate users against information stored elsewhere, you must write the Java class that performs this authentication. You ll find more information on this subject in To perform user-defined authentication on page 285. To illustrate how to assign a privilege to a user when the user successfully logs in to an application, this section shows how an application that uses this strategy was put together. The example is a variation on the sports-news Web site discussed earlier. In this version of the example, when a subscriber goes to the site, the user does not have the privileges to read feature articles. The user must elect to log in to the application against information maintained by the operating system. If the user logs in successfully, the application grants the user the privilege Subscribed, which enables the user to read protected pages. 277

299 Chapter 12: Access Control The main steps involved in adding the authentication feature to the application are: adding to your project a login page which contains a form that requests login information and success and failure pages adding the Login widget to the application In addition, it may be necessary to change the configuration of the Application Server. You will find detailed information about how these steps were performed in the following sections. To add the pages required by the Login widget 1 Add to your project a page that will be used by the Login widget to present a login form to the user. The easiest way to perform this task is to use the application-login-page template supplied with HAHTsite. To use this template: From the File menu, select New > Page... From the list of templates in the New Page dialog, choose the User Login Page template, and click the OK button. The page shown below is opened. Customize the login page if you want to. Give the page a name, and save the page. From the Publish tab of the Page Properties dialog, promote the page to dynamic or secure static so that the page will be published to the Application Server. 278

300 Chapter 12: Access Control Of course, you can also create your login form by hand. The form should include a User Name text box, a Password text box, a Domain text box (if appropriate), and a Submit button. Note - The form can also be placed on the page that contains the Login widget. The table below shows how you should name the text fields in the form to minimize the number of attributes you will need to customize in the Login widget itself. Text box label User Name Password Domain Text field name txtusername txtuserpassword txtuserdomain The action you associate with this form should have the following attributes: Type: Project Item Path: None. (Leave this field blank.) If you supply these values, submitting the form will cause the application to load the previous page. In the present case, the application will load the page containing the Login widget. One last point. Make sure that the login page is dynamic or secure static so that it will be published to the Application Server. 2 Create a success page. This page will be loaded if the user successfully logs in. Note - The success (or failure) page can also be the same as the page that contains the Login widget. Set this page s properties to make the page dynamic or secure static. 3 Create a failure page. This page will be loaded if the user login is unsuccessful. Set this page s properties to make the page dynamic or secure static. To add the Login widget 1 Create a blank page to hold the Login widget. 279

301 Chapter 12: Access Control When the application calls the page containing the Login widget, the widget will cause the login page (the page containing the login form) to be displayed. 2 Drag a Login widget from the Project window to the page. 3 Set the widget s properties. The following four tables explain what information you need to supply on the four tabs of the Login Properties dialog. The first tab of the dialog, labeled General, enables you supply a name for the widget and to specify some general characteristics of the widget s behavior. Form field Name Reset session privileges on successful login check box Description Type the name of the Login widget here. When a user s session loads a page containing a Login widget, the user may already have some session privileges. If this check box is checked, the user s current privileges are taken away, and the user is assigned the privileges indicated on the Privileges tab of the Login Properties dialog. If the check box is not checked, the user receives the privileges indicated on the Privileges tab in addition to any current privileges. 280

302 Chapter 12: Access Control Form field Remember successful login check box Only one login per session check box Description This option enables you to specify whether the user must log in each time the user goes to the page containing the Login widget (unchecked) or whether the user must log in only the first time the user goes to that page (checked). An application may contain more than one Login widget. If this check box is checked, the user will be prompted to log in only once per session. The Navigation tab of the Login Properties dialog enables you to indicate the pages the Login widget should call: to display a login form if the login succeeds if the login fails Form field Login page: Page containing widget Description Select this radio button if the page containing the Login widget also contains the login form the user fills out to log in. 281

303 Chapter 12: Access Control Form field Login page: Another page Success page: Page containing widget Success page: Another page Failure page: Page containing widget Failure page: Another page Description Select this radio button if the page containing the Login widget and the page containing the login form are different pages. In the example project, this is the case. Select this radio button if the page containing the Login widget is also your success page. Select this radio button if the page containing the Login widget and your success page are different pages. In the example project, this is the case. Select this radio button if the page containing the Login widget is also your failure page. Select this radio button if the page containing the Login widget and your failure page are different pages. In the example project, this is the case. The Login tab of the Login Properties dialog enables you to indicate the names of the text boxes in which the Login widget will look for login information: 282

304 Chapter 12: Access Control Form field User Name User Password User Domain Description The name of the text box in the login form in which the user enters a user name. The name of the text box in the login form in which the user enters a password. The name of the text box in the login form in which the user enters a Windows NT domain name. This information is only used if the user is logging on against authentication information maintained by Windows NT. Note - If you create your login page as described in To add the pages required by the Login widget on page 278, you won t have to modify the Login tab of the dialog. On the Privileges tab of the Login Properties dialog, you indicate whether a logged-in user should receive a predefined set of privileges or whether the Login widget should look up the user s privileges in a privilege repository. The current example is using the former option: a user receives the Subscribed privilege upon logging in. For information on looking up privileges in a privilege repository, see Granting privileges on a user-name basis on page

305 Chapter 12: Access Control Form field Use privilege repository radio button Grant privileges on login radio button Description Select this button to indicate that the widget should read the user s privileges from a database or some other repository. Select this button to indicate that a user who successfully logs in should receive the privileges shown in the list. You can add privileges to and remove privileges from the list by using the Add... and Remove buttons. To configure the Application Server Set the access-control properties of your Application Server so that the Authentication Type is either Operating System or User Defined. (By default, this property is set to Operating System.) For specific instructions on how to configure this property, see Chapter 3, Performing administrative tasks, in the HAHTsite Application Server Administration Guide. If you select Operating System authentication, the Login widget will use a Java class called OSAuthentication to authenticate users. This is the scenario in the sample project. The OSAuthentication class, which implements the Authentication interface, uses the operating system s login mechanism to authenticate user logins. This authentication is performed on the HAHTsite Background Host on which the HAHTsite session is running. Before you use the OSAuthentication class with HAHTsite, you should be aware of the following platform-specific requirements: Windows NT requires that a process hold a Windows NT privilege named Act as a part of the Operating System in order to validate a user login. The HAHTsite Background Service that performs this validation runs as the System Account by default. This account has the required privilege. Therefore, you should not change the user account for the HAHTsite Background Service if you want to use operating-system authentication. The Developer s Edition of the HAHTsite Application Server cannot actually perform operating-system authentication because it runs as a desktop application. Consequently, when you re running the Developer s Edition, the method used to authenticate users always returns true unless the user name is InvalidUser, the password is InvalidPassword, or the domain value is InvalidDomain. This 284

306 Chapter 12: Access Control arrangement enables you to test success cases with different user names without knowing the corresponding passwords, and to test failure cases with the Developer s Edition. For HAHTsite Background Hosts running on UNIX, you can use OSAuthentication only if a root installation of the Application Server has been performed. If you select User Defined authentication, you must write and add to your project a Java class that performs the authentication. You must also write code that will set a variable of your application s Application object at runtime. This variable must contain the name of the authentication class you ve written. For further information about implementing a custom authentication class, see To perform user-defined authentication below. To perform user-defined authentication 1 In your project s Packages folder, create a Java source file and write your authentication class. This class must implement the Authentication interface and, thus, must define a method named authorizeuser: boolean authorizeuser(string auserid, String apassword, String adomain) This method should return true if the user is authenticated, and false otherwise. Appendix C, Code Examples, presents a sample authentication class that authenticates users against information stored in a database. 2 Add to your project the code that will enable your application to determine at runtime which Java class it should use for user-defined authentication. This task differs somewhat between Java and HAHTtalk Basic projects. Java projects. Modify your project s HahtApplication class by editing the source file HahtApplication.java. Add to the class s onstart method code to identify your custom authentication class. You do this by calling the method setauthenticationclassbyname. Java public void onstart(com.haht.project.applicationevent anevent) { this.setauthenticationclassbyname("customauthentication"); } 285

307 Chapter 12: Access Control HAHTtalk Basic projects. Add a code page to your project, and in this file define a public function called HahtSessionOnStart. This function should call the Application object s setauthenticationclassbyname method to identify the name of the user-defined class that will perform the authentication. HAHTtalk Basic Public function HahtSessionOnStart As Boolean Dim AuthSuccess As Boolean AuthSuccess = _ HahtApplication.setAuthenticationClassByName _ ("CustomAuthentication") HahtSessionOnStart = AuthSuccess End Function Caution - In a Java project, a publish operation does not place your custom authentication class in the! Application Server s default Java Class Directory or in a default directory on the System Java Class Path. Before running your application, either move your class file to a directory where the Application Server can find it, or change your System Java Class Path to include the directory where your class file resides. Tip - While debugging a custom authentication class, turn on the project property Run each app instance in separate process. This setting will cause the Application Server to reload your authentication class each time you run your application. Authenticating users with the Authentication interface The Login widget authenticates users by calling: the authorizeuser method of a class that implements the Authentication interface the Session class s addprivilege or addprivileges method Since you also have access to these methods, you can call the methods directly, instead of using the Login widget. 286

308 Chapter 12: Access Control For example, assume that you wanted to modify the sports-news project so that it did not use the Login widget. You could have users who want to log in go not to a page containing a Login widget, but directly to the page containing the login form. You could then change the action of the form so that the form calls one of the subroutines shown below. Java package AccessCtrlJava1; import com.haht.*; import com.haht.project.*; class AuthenticateUser { public void run(request arequest, Response aresponse) { /* Authenticate the user and assign the user the privilege Subscribed if the authentication is successful. */ String username = arequest.geturlfield("txtusername"); String password = arequest.geturlfield("txtuserpassword"); String domain = arequest.geturlfield("txtuserdomain"); boolean authenticated = Haht.getSession(). getauthentication(). authorizeuser(username, password, domain); if (authenticated == true) { Haht.getSession().addPrivilege("Subscribed"); HAHTPage successpage = Haht.getSession(). returnhahtpageobject("accessctrljava1.hssuccess"); successpage.run(arequest, aresponse); } else { HAHTPage failurepage = Haht.getSession(). returnhahtpageobject("accessctrljava1.hsfailure"); failurepage.run(arequest, aresponse); } } } 287

309 Chapter 12: Access Control HAHTtalk Basic Sub AuthenticateUser Dim arequest As Object Dim username As String Dim password As String Dim domain As String Dim authenticated As Boolean Set arequest = Haht.getRequest() username = arequest.geturlfield("txtusername") password = arequest.geturlfield("txtuserpassword") domain = arequest.geturlfield("txtuserdomain") authenticated = HahtSession.getAuthentication(). _ authorizeuser(username, password, domain) If (authenticated = True) Then HahtSession.addPrivilege "Subscribed" HS_Success Else HS_Failure End If End Sub Generally, it s preferable to use the Login widget in your application because this approach requires less coding and gives you more features. But occasionally you may need to authenticate users using the Server Object Model methods. Letting the Web server authenticate users In addition to authenticating users against information maintained by the operating system or information in a user-defined location, you may want to authenticate users against information maintained by your Web server. In this case, you don t use the Login widget or methods defined in the Server Object Model. You just configure your Web server so that URLs requesting dynamic or secure-static pages from a HAHTsite Application Server cause the Web server to send an authentication request to the browser. To use your Web server s authentication mechanism 1 Configure your Web server to authenticate a user who requests a dynamic or secure-static page. 288

310 Chapter 12: Access Control 2 After the user is authenticated, assign the user one or more privileges using the Session class s addprivilege or addprivileges method. 3 Configure your Application Server s access-control properties so that its Authentication Type is None. Note - If you need a user s user name for any reason for example, you may want to look up a user s privileges in a database you can get it by calling the Request class s getservervariable method to obtain the value of the environment variable REMOTE_USER. For information about looking up user privileges in a privilege repository, see Granting privileges on a user-name basis on page 289. Granting privileges on a user-name basis The preceding section explained how to require a user to log in to an application and to grant a user a set of privileges upon a successful login. In this arrangement, everyone who logs in to the application gets the same privileges. This approach may work fine for the sports-news project, but other applications may require that different users get different privileges. For example, consider any application that accesses a database. Some users should not be able to access the database at all (no privileges), some people should have read-only access to the database ( User privilege), and some people should be able to read from and write to the database ( User and Admin privileges). Building on the information presented in earlier sections, this section explains how to grant privileges on a user-by-user basis. For this type of scheme to work, you must first create a privilege repository. This repository can be a database table, but need not be. It could also be an LDAP directory or a regular file. The only hard-and-fast rule is that the privilege repository must specify the privileges to be given to a user with a particular user name. Once you ve decided how to implement your privilege repository, there are several scenarios to consider: Your application uses a Login widget, and your privilege repository is a database table. Your application uses a Login widget, and your privilege repository is not a database table. Your application does not use a Login widget. 289

311 Chapter 12: Access Control The upcoming sections explain how to handle each of these situations. Using a Login widget and a database privilege repository If you have an application like the sports-news project described in Granting privileges to logged-in users on page 276 that assigns all users who log in the same set of privileges, there are three tasks you ll have to perform to have the application assign each user a custom set of privileges read from a database: Create a database table that contains information about each user s privileges. Configure the Login widget to look up a user s privileges in a privilege repository. Configure the Application Server to look for a user s privileges in your database. The following sections explain in detail how to perform these tasks. To create the database privilege repository 1 Create a database table named hssecurityprivileges. 2 In this table, create the fields shown in the table below. Field name Description Data type hsuserid hsprivilege The user s user ID. This ID does not have to be unique. The name of a privilege belonging to the user. String String Each row in the table specifies one privilege belonging to a user. The Login widget reads the entire table to obtain a list of a user s privileges. 3 Enter user names and privileges in the table, one user name and privilege per row. If a user has three privileges, you should add three rows to the table for that user. To configure the Login widget 1 Open the Login Properties dialog for the Login widget. 290

312 Chapter 12: Access Control 2 Go to the Privileges tab. 3 Select the radio button labeled Use privilege repository. When you choose this setting, the Login widget behaves as follows: After authenticating a user, the widget opens a connection to a database known to the Application Server (the database containing the table hssecurityprivileges) and reads the user s privileges from the appropriate table using a method of the DBUserProfile class. It then assigns those privileges to the user s session. To configure the Application Server 1 Change your Application Server s access-control properties so that the Privilege Repository Type is Database. 2 Supply a DB Privilege Repository Connect String. If you re not sure how to write the connection string, you might want to use the IDE to create an ADO connection to the privilege database. When you create this connection, if you use the IDE s Connection Browser to point to your database, the IDE will create a connection string for you. You can copy this connection string and paste in into the DB Privilege Repository Connect String text box. Using a Login widget and a nondatabase privilege repository It s also possible to use the Login widget with a nondatabase version of the privilege repository to assign privileges to users. However, to make this work, you must write a Java class that contains a method that takes a user name as an argument and returns a set of privileges. This subject is discussed in more detail in To create a Java class and make it known to your application on page 292. There are three basic tasks you must perform to have your application assign each user a custom set of privileges read from a user-defined location: Configure the Login widget to look up a user s privileges in a privilege repository. Configure the Application Server to look for a user s privileges in a user-defined location. Write a custom user-profile class containing a lookupprivileges method that returns a list of privileges for a particular user. And make this class known to your application. 291

313 Chapter 12: Access Control The following sections explain in detail how to perform these tasks. To configure the Login widget 1 Open the Login Properties dialog for the Login widget. 2 Go to the Privileges tab. 3 Select the radio button labeled Use privilege repository. When you choose this setting, the Login widget behaves as follows: After authenticating a user, the widget checks an Application Server property to determine whether your privilege repository is in a database or elsewhere. When it determines that your repository is not in a database, the widget calls the lookupprivileges method of a class you ve written and made known to your application. (You must write this method since you re the only one who knows where and in what format your privileges data is stored.) Finally, the widget assigns the privileges it retrieves to the user s session. To configure the Application Server Change your Application Server s access-control properties so that the Privilege Repository Type is User Defined. To create a Java class and make it known to your application 1 In your project s Package folder, create a Java source file and write your custom user-profile class. This class must implement the UserProfile interface and, thus, must define a method lookupprivileges: Privileges lookupprivileges(string auserid) The Privileges object returned by this method is a container for a set of privileges. For more information about the Privileges class, see Privileges class on page Add to your project the code that will enable your application to determine at runtime which Java class it should use for user-defined privilege lookup. This task differs to a degree between Java and HAHTtalk Basic projects. Java projects. Modify your project s HahtApplication class by editing the source file HahtApplication.java. Add to the class s onstart method code to identify your custom privilege-lookup class. You do this by calling the method setuserprofileclassbyname. 292

314 Chapter 12: Access Control Java public void onstart(com.haht.project.applicationevent anevent) { this.setuserprofileclassbyname("customuserprofile"); } HAHTtalk Basic projects. Add a code page to your project, and in this file define a public function called HahtSessionOnStart. This function should call the Application object s setuserprofileclassbyname method to identify the name of the user-defined class that will perform the privilege lookup. HAHTtalk Basic Public function HahtSessionOnStart As Boolean Dim ProfSuccess As Boolean ProfSuccess = HahtApplication.setUserProfileClassByName _ ("CustomUserProfile") HahtSessionOnStart = ProfSuccess End Function Using the Server Object Model You don t have to use HAHTsite s Login widget to look up a user s privileges in a privilege repository and assign them to the user s session. Your application can call the lookupprivileges method (of a class that implements the UserProfile interface) and the Session class s addprivileges method directly to accomplish the very same thing. This would be a useful approach to take if you were using your Web server to perform user authentication, for example. The list of steps you must perform to look up and assign privileges in this way is as follows: 1 Create your privilege repository. If you want to store information about users and their privileges in a database table, follow the directions in To create the database privilege repository on page 290. If you choose to store the information elsewhere, just remember that the Java method that looks up privileges takes a user name as its argument and returns an object of type Privileges, which contains a list of privileges. Since you must implement this method 293

315 Chapter 12: Access Control yourself (if your privilege repository is not a database table), you can store the data in any format you choose. 2 Configure your Application Server s Privilege Repository Type and supply a database connection string, if necessary. If your privilege repository is a database table, choose a Privilege Repository Type of Database, and enter the connection string the Application Server will need to establish a connection with your database. If your privilege repository is not a database, choose a Privilege Repository Type of User Defined. 3 If your privilege repository is not a database, implement a custom user-profile class, and modify your project so that it will know about your user-profile class at runtime. See To create a Java class and make it known to your application on page 292 for more information about how to perform this step. 4 Add to your application code that calls the lookupprivileges and addprivileges methods. The example below shows how your application might make these calls. The example assumes that the user fills in a login form and that the form s action is to call a subroutine that authenticates the user and looks up his or her privileges. The lines highlighted in the subroutine are the ones that have to do specifically with looking up privileges and assigning them to a user session. 294

316 Chapter 12: Access Control Java package AccessCtrlJava1; import com.haht.*; import com.haht.project.*; import com.haht.access.*; class AuthenticateUser { public void run(request arequest, Response aresponse) { String username = arequest.geturlfield("txtusername"); String password = arequest.geturlfield ("txtuserpassword"); String domain = arequest.geturlfield("txtuserdomain"); Privileges privs = new Privileges(); Session sess = Haht.getSession(); boolean authenticated = sess.getauthentication(). authorizeuser(username, password, domain); if (authenticated == true) { UserProfile prof = sess.getuserprofile(); try { privs = prof.lookupprivileges(username); } catch (com.haht.hahtexception except) { } String privstrings[] = privs.getstringarray(); sess.addprivileges(privstrings); HAHTPage successpage = Haht.getSession(). returnhahtpageobject("accessctrljava1.hssuccess"); successpage.run(arequest, aresponse); } else { HAHTPage failurepage = Haht.getSession(). returnhahtpageobject("accessctrljava1.hsfailure"); failurepage.run(arequest, aresponse); } } } 295

317 Chapter 12: Access Control HAHTtalk Basic Sub AuthenticateUser Dim arequest As Object Dim prof As Object Dim privs As Object Dim sessionprivs As Object Dim username As String Dim password As String Dim domain As String Dim authenticated As Boolean Set arequest = Haht.getRequest() username = arequest.geturlfield("txtusername") password = arequest.geturlfield("txtuserpassword") domain = arequest.geturlfield("txtuserdomain") authenticated = HahtSession.getAuthentication(). _ authorizeuser(username, password, domain) If (authenticated = True) Then Set prof = HahtSession.getUserProfile() Set privs = prof.lookupprivileges(username) Set sessionprivs = HahtSession.getPrivileges() If (sessionprivs.merge(privs)) Then ' Check for error here. End If HS_Success Else HS_Failure End If End Sub Server Object Model methods HAHTsite s Server Object Model contains a number of classes that define methods relating to access control: Session, Privileges, and Application. The model also defines two interfaces Authentication and UserProfile that you make use of when implementing user-defined authentication or user-defined privilege lookup. The following pages list the relevant methods of these classes and interfaces. 296

318 Chapter 12: Access Control Session class A Session object keeps track of information related to the state of an application with respect to a single user. The methods of the Session class that relate to access control are listed below. Method addprivilege addprivileges getauthentication getauthenticationtype getprivileges getuserprofile hasprivilege hasprivilegesforitem removeprivilege removeprivileges Description adds a single privilege to a user s session adds a set of privileges to a user s session. Available in Java projects only. gets a reference to the session s authentication object. This object may have been instantiated from the OSAuthentication class or from a user-defined authentication class. returns a constant indicating the type of the session's authentication object: OS authentication, user-defined authentication, or none returns the set of privileges that have been granted to the current session gets a reference to the session s user-profile object. This object may have been instantiated from the DBUserProfile class of from a user-defined class. returns true if the user s session has a specific privilege returns true if a session has all of the privileges required to access a particular project item removes a privilege from the set of privileges held by the user s session removes some or all of the privileges associated with the user s session. Available in Java projects only. 297

319 Chapter 12: Access Control Privileges class A Privileges object is a container for a set of privileges. The methods listed below make up the interface to objects of this type. Method add clear getstringarray hasall hasone has merge remove setstringarray Description adds a privilege to a list of privileges removes from a Privileges object all the privileges it contains at the time of the call returns the privileges contained in a Privileges object as an array of strings. Available in Java projects only. returns true if the Privileges object being used to access this method includes all of the privileges contained in another Privileges object returns true if the Privileges object being used to access this method includes any one of the privileges contained in another Privileges object returns true if the Privileges object being used to access this method contains a specific privilege merges the contents of two Privileges objects removes a privilege from a Privileges object adds to a Privileges object all of the privileges contained in an array of strings. Available in Java projects only. Application class The Application class provides methods that enable you to set or read the name of: a user-defined authentication class a user-defined privilege lookup class 298

320 Chapter 12: Access Control Method setauthenticationclassbyname setuserprofileclassbyname Description enables you to specify the name of the user-defined authentication class to be used by the application enables you to specify the name of the user-defined privilege lookup class to be used by the application Authentication interface An object instantiated from a class that implements the Authentication interface is responsible for authenticating a user who is attempting to log in to an application. The object takes a user ID, a password, and possibly a Windows NT domain name as input and compares that information with the information in a user name/password repository. The interface to this object is shown below. Method authorizeuser Description authenticates a user by comparing the user s login information with information in a user name/password repository UserProfile interface An object instantiated from a class that implements the UserProfile interface holds information about the session privileges associated with a particular user. It gets its information from a database table or a user-defined repository. The interface to this type of object is shown below. Method lookupprivileges Description reads a repository to determine what session privileges are to be granted to a particular user and returns those privileges as an object of type Privileges 299

321 Chapter 12: Access Control 300

322 Connecting to COM Objects 13 Introduction Calling DLLs Declaring a DLL in HAHTtalk Basic Example DLL declarations Mapping HAHTtalk Basic types to DLL data types Using COM objects with HAHTtalk Basic The CreateObject function A COM Server example Background HAHTMem methods

323 Chapter 13: Connecting to COM Objects Introduction If your Web server is running on a Windows NT machine, you can extend the functionality of your HAHTsite applications by connecting the applications to DLLs and COM objects. (A DLL is a dynamic link library. COM stands for Component Object Model.) In a HAHTsite application, DLLs and COM servers run as server-side objects (in contrast to client-side objects such as JavaScript and VBScript). This chapter explains how to call DLLs and connect to COM/DCOM objects in a HAHTsite Basic project. You can accomplish the same thing in a Java project using native methods; consult the documentation for your Java compiler or the HAHTsite knowledge base at Calling DLLs The method for calling a DLL from a HAHTtalk Basic application is the same as calling a DLL from a Visual Basic application: 1 Obtain, from the author of the DLL, the number of DLL functions and parameters. 2 Use the HAHTtalk Basic Declare statement to declare, typically in the application s globals.hbs file or in an include file, the DLL as a HAHTtalk Basic function or subroutine. In many cases, the DLL s author will provide a Basic file with the DLL s functions and subroutines already declared in the Basic syntax. 3 Call the function or subroutine from a HAHTtalk Basic code page or HTML page. Declaring a DLL in HAHTtalk Basic The syntax for the HAHTtalk Basic Declare statement is described completely in the HAHTsite on-line help. Here is a summary: Declare {Sub Function} name[typechar] [CDecl Pascal ] _ [Lib "LibName$" [Alias "AliasName$"]] _ [([ParameterList])] [As Type] 302

324 Chapter 13: Connecting to COM Objects Item Sub Function name Cdecl Pascal Lib "LibName" Alias "AliasName" ParameterList As Type Description If the DLL function is void (the function returns no value), use Sub. If the DLL function returns a value, use Function. The name of the DLL function. If the function is called CalcSalesTax in C/C++, use the same name in the HAHTtalk Basic declaration. Order in which parameters are passed between the calling program and the DLL. The default ordering is Pascal, which passes parameters starting from the first parameter. If the DLL function explicitly uses the Cdecl keyword in its definition, use the Cdecl keyword in your declaration. Lib specifies that the DLL is external to the calling program. LibName is the name of the DLL (in quotes). LibName can include a path and need not include the.dll extension. Use an alias when the name of an external routine conflicts with the name of a HAHTtalk Basic internal routine or when the external routine name contains invalid characters. The AliasName parameter must appear within quotes. Any parameters, and their types, sent to the DLL. See Mapping HAHTtalk Basic types to DLL data types on page 304. If the DLL is void (returns no value) and is declared as a Sub, do not include this item. If the DLL is declared as a Function, include the type. The valid return types are: Integer, Long, String, Single, Double, Date, Boolean, and data objects. Note - HAHTtalk Basic does not support DLL functions that return the following data types: Currency, Variant, fixedlength strings, user-defined types, or COM objects. For more information, see the Declare topic in HAHTsite s on-line help. Example DLL declarations Here is a the API of a sample DLL written in C, followed by the HAHTtalk Basic declaration for the DLL. float declspec(dllexport) CalcSalesTax(float SaleAmount, _ 303

325 Chapter 13: Connecting to COM Objects float TaxAmount) Declare Function CalcSalesTax Cdecl Lib "SalesTax" _ (ByVal SaleAmount As Single, _ ByVal TaxAmount as Single) As Single Here are other examples of HAHTtalk Basic DLL declarations. These DLL calls are used in the XtremeCatalog module of the Xtreme_Demo in the HAHTsite introduction project. Declare Function LogonUser Lib "advapi32" _ Alias "LogonUserA" (ByVal lpszusername As String, _ ByVal lpszdomain As String, ByVal lpszpassword As String, _ ByVal dwlogontype As Long, ByVal dwlogonprovider As Long, _ phtoken As Long) As Long Declare Function CloseHandle Lib "kernel32" _ Alias "CloseHandle" (ByVal hobject As Long _ As Long Mapping HAHTtalk Basic types to DLL data types Many DLLs are written in C or C++. The next table shows the relationship between C/C++ data types and HAHTtalk Basic data types. C Data Type short (16-bit integer) long (32-bit integer) short * (ptr to 16-bit integer) long * (ptr to 32-bit integer) float double HAHTtalk Basic Data Type ByVal Integer ByVal Long ByRef Integer ByRef Long ByVal single ByVal double 304

326 Chapter 13: Connecting to COM Objects C Data Type char * structure * HAHTtalk Basic Data Type ByVal string If the DLL is writing to the string, you must preallocate the string space in HAHTtalk Basic. One way to do this is: TheStr = String$(TheMaximumLen,0) Where TheStr is the string you are passing and TheMaximumLen is the maximum length to which the string could be populated. The String$ function populates the string with null bytes, which is compatible with the C language convention for string termination. ByRef structure_type Each element in the HAHTtalk Basic structure must be explicitly defined, for example TheStr As String*20 Additionally, the DLL must have been built on single-byte alignment. Using COM objects with HAHTtalk Basic You create a COM object (an instance of a COM Server) with the HAHTtalk Basic function CreateObject function. You can then access the object s methods and properties from your HAHTtalk Basic code Once you have a COM object in a HAHTtalk Basic variable of type Object, you access the object s properties and methods using the "." syntax. The CreateObject function Syntax Function CreateObject(COMObjectName) As Object Description Creates an instance of the COM Server specified in the COMObjectName parameter. The supplier of the COM Server is responsible for providing you with the methods and properties of the server. 305

327 Chapter 13: Connecting to COM Objects You must register the COM Server with the Windows Regsvr32 utility, or with a similar facility such as HAHTtalk Basic s DLLRegisterServer function. HAHTsite locates ActiveX/COM objects by looking in the registry on the HAHTsite Application Server s machine. For example, if you use the function CreateObject("Excel.Application"), HAHTsite looks up Excel.Application in the system registry to find the binary file for that object. Parameters Parameter Type Description COMObjectName String Registered COM object name Example The following subroutine creates a COM Server object called cobj from the COM Server HAHTMem. Sub DemoHAHTMem() Dim cobj As Object ' Create an instance of the COM server Print "Creating An Instance to the HAHTMem Server...";"<P>" Set cobj = CreateObject("HAHTMem.cMemMgr") ' ' Code to use the COM Server. ' End Sub A COM Server example This section describes a simple example of connecting HAHTsite to a COM Server called HAHTMem. The HAHTMem COM Server provides for shared-memory workspaces among multiple instances of a HAHTsite application running on the same Windows machine. Note - A project that contains the HAHTMem COM Server is available online in the HAHT Software knowledge base ( 306

328 Chapter 13: Connecting to COM Objects Background One of the features of the HAHTsite Application Server is its ability to maintain state. At a conceptual level, there are different kinds of state you might want to maintain: state that is "per-instance" of a HAHTsite application. This is the kind of state you get when you declare a global HAHTtalk Basic variable. Each StateId (i.e., user) gets his or her own per-instance state. Any global variables (defined in globals.hbs) are part of that user s per-instance state. A change that User A makes to his global variable MyVariable does not affect what User B gets when she accesses her MyVariable global variable. state that is shared across all instances of the same application running on the same machine. For example, information kept in a database table to which the application attaches falls into this category. However getting and setting cross-instance values in a database carries the overhead of accessing the database. Another approach to sharing state across instances of an application is to allocate memory that can be accessed by all instances of the application. In the simplest case, you might simply keep a count of the number of copies of the application that were active the number application instances. Or, you could keep more sophisticated usage statistics. Another example might be a chat room or bulletin board application in which you need to keep a list of currently active users so that all users could see what other users were logged in. This is what the HAHTMem COM Server provides each instance of an application can attach to the COM Server and get access to a common shared memory area. HAHTMem methods Here is a description of the methods provided by the HAHTMem COM Server. OpenWorkspace HATHMem manages named workspaces that contain one or more variables. If an OpenWorkspace command uses a workspace name that doesn t exist, the workspace is created. If the workspace already exists, the in-use count for that workspace is incremented. OpenWorkspace returns to the caller an ID which is used by the caller for all subsequent operations against the workspace. CloseWorkspace detaches the caller from the workspace. The workspace's in-use count is decremented by 1. If the workspace in-use count reaches 0, the workspace is deleted. 307

329 Chapter 13: Connecting to COM Objects OpenVar opens a variable in an existing workspace. All variables are referred to in the syntax of Workspace:Variable, where Workspace is the workspace name and Variable is the variable name (for example, FileLocks.MainLogFile). All workspace variables are stored as HAHTtalk Basic Variant data types in the HAHTMem COM Server. CloseVar closes a variable in a workspace. WriteVar writes a value to a variable in a workspace. ReadVar reads the value of a variable in a workspace. LockVar locks access to a workspace variable to the current caller. Returns True or False depending whether the lock request was successful. If the lock request returns False, another application currently has the variable locked, the application should perform an OS Sleep() and then try again to lock the variable. UnlockVar unlocks exclusive access to a workspace variable. LockWorkspace locks a workspace for exclusive access by the current application. Returns True or False depending if Lock request was successful. UnlockWorkspace unlocks a workspace for exclusive access by the current application. 308

330 HAHTsite CORBA Capabilities 14 Overview Using CORBA with the HAHTsite IDE HAHTsite as a CORBA client HAHTsite as a traditional CORBA server CORBA and the HAHTsite Server Object Model Other Information References

331 Chapter 14: HAHTsite CORBA Capabilities Overview HAHTsite gives you the ability to integrate Web applications with objects created using CORBA, the Common Object Request Broker Architecture. Among other things, this flexible mechanism can be used to: integrate HAHTsite Web applications with large-scale and legacy systems provide a direct connection between a client and the Application Server, bypassing the Web server allow external programmatic control over the operation of the Application Server, including the initiation of HAHTsite application sessions While HAHTsite can be used to create sophisticated Web applications, many customers already have complex computing environments built over many years. Often, a major reason for providing Web capabilities is the exposure of parts of these systems to the external world via the Internet, or access by the enterprise through an intranet. Integration with CORBA allows HAHTsite to connect new Web applications with a wide variety of existing enterprise systems. What is CORBA? This chapter assumes familiarity with CORBA programming. CORBA (the Common Object Request Broker Architecture) is the leading method for building large-scale, distributed objects and applications. It is defined by the Object Management Group, a consortium of over 800 companies. More information is available from the OMG Web site: What does HAHTsite/CORBA interoperation mean? The software bundled with HAHTsite includes Inprise (formerly Visigenic) VisiBroker for Java. HAHTsite applications written using the HAHTsite Server Object Model can incorporate calls to the VisiBroker interfaces and thereby act as standard CORBA objects. Using CORBA s built-in capabilities, they can communicate with and become part of an enterprise built of distributed CORBA objects. Information from remote CORBA systems, such as mainframes, can be obtained by these CORBA-enhanced HAHTsite applications. This data can then be used in any manner within the HAHTsite application, providing a flexible, complete method to present enterprise information on the Web. 310

332 Chapter 14: HAHTsite CORBA Capabilities In addition to this peaceful coexistence, there are several extensions to the HAHTsite Server Object Model that provide CORBA interfaces, allowing CORBA systems to operate directly on some HAHTsite server objects. This level of integration allows an external, non-hahtsite application to connect as a CORBA client to a CORBA-enabled HAHTsite application acting as a CORBA server. Such a client can initiate and control a HAHTsite session, making use of session capabilities such as automatic timeout. CORBA can also provide a Java applet running in a browser the ability to communicate with a HAHTsite application without the overhead of the HTTP protocol. For applets requiring substantial or very dynamic data from the server, this can be very beneficial. Outside the support in HAHTsite for writing CORBA-enabled applications, HAHTsite is not built on and does not directly depend on CORBA. If you have no need to develop CORBA-based applications, you need not install VisiBroker for Java. Using CORBA with the HAHTsite IDE The HAHTsite IDE can be used to build VisiBroker-enhanced HAHTsite applications, handling the details of compilation of Java and CORBA code, and putting the compiled classes in the proper location for use. In order to accomplish this, the IDE provides a number of configuration points. Handling CORBA projects If the Application and Session objects are to be exposed as CORBA objects, the check box Expose Session and Application Objects to CORBA must be selected from the project s Edit > Properties dialog box. Setting this check box causes the IDE to generate CORBA-enabled HahtApplication and HahtSession classes when the project is built, using the VisiBroker TIE mechanism. This is not required if the application represents a CORBA client or a straightforward CORBA server that creates its own objects. You add an IDL file to the project in the same way that you add other file types. File > New > IDL will create a new IDL file that can be added to the project, or you can import an existing IDL file from the main File menu or by right-clicking in the Project view. When you publish a CORBA-enabled project, the IDL compiler produces a number of Java files in the staging directory. These files are compiled, and the 311

333 Chapter 14: HAHTsite CORBA Capabilities resulting classes are stored on the Web server or Application Server, depending on how the IDE is configured. As with other file types, individual IDL files may be selected and compiled by using the IDL > Build menu. Note - The Visibroker IDL compiler is not included with HAHTsite. Setting options for CORBA The addition of CORBA capabilities adds several dialogs to the IDE configuration. A new Java file type is created for CORBA projects. The IDE distinguishes Java code that is to be run on the Application Server from code that is to be run elsewhere, and different Java compilers may be specified for the two types of Java files. Under the Tools > Options... > Java > Add dialog, a Java compiler may be added for Java files that are part of CORBA projects. The setup of the default Java compiler profile for CORBA-generated Java files sets up the proper Java compiler switches and places the necessary Visigenic JAR files (vbjapp.jar and vbjorb.jar) in the compiler s Class Path argument. There is a new dialog under Tools > Options... > CORBA that allows IDL compilers to be configured. Different IDL compilers may be specified depending on whether the output code is to be run on the Application Server or elsewhere. As with the Java compilers, different compiler options may be set on an IDL compiler using the Add or Modify buttons. A typical use might be to instruct the IDL compiler to produce ORB-independent code if the application stubs and skeletons are to be compiled with compilers from more than one ORB vendor. 312

334 Chapter 14: HAHTsite CORBA Capabilities Note - For detailed instructions on how to add or modify an IDL compiler profile, see Chapter 2, Using the IDE/IP s Windows and Toolbars, in the HAHTsite IDE and IP User s Guide. For an individual project, the Edit > Properties > CORBA Compilers dialog allows you to override the IDL compiler defaults just described. By choosing an IDL compiler (the default one is the IDL-to-Java Visibroker compiler) and clicking Modify, you can change which compiler is used to translate IDL files to Java. You can also modify the settings used for the IDL compilation process, such as the root directory and options to the compiler 313

335 Chapter 14: HAHTsite CORBA Capabilities. By default, the VisiBroker IDL compiler generates several Java files for each CORBA interface, placing them in the staging directory. The following class files are generated when these files are compiled with the CORBA Java compiler. File Name module_name\interface_name.class module_name\_st_interface_name.class module_name\_tie_interface_name.class module_name\interface_nameimplbase.class module_name\interface_namehelper.class module_name\interface_nameholder.class module_name\interface_nameoperations.class module_name\_example_interface_name File Type Both Stub Both Skeleton Stub Skeleton Skeleton Skeleton Not all classes are necessarily generated for each IDL interface, depending on the settings of the IDL compiler options. For each IDL file, properties may be set to determine where the compiled Java classes will be placed. Right-click on the IDL file and choose Properties to bring up the IDL Properties dialog. By default, all classes are placed in the Application Server s staging directory. The interface may be used to specify 314

336 Chapter 14: HAHTsite CORBA Capabilities whether the stub classes (those required for a CORBA client) are compiled to the Application Server, the Web server, or both. The same choices are available for the skeleton classes (those required for a CORBA server). HAHTsite as a CORBA client HAHTsite allows you to build CORBA clients in the IDE and to run those clients in the Application Server. The CORBA IDL files for a particular project may be imported or created using the HAHTsite IDE editor. IDL files are recognized by the IDE. When the project is published, the IDL compiler is invoked to produce the Java client stubs and server skeletons. HAHTsite places the compiled stub classes in their appropriate location in the HAHTsite directory hierarchy. A common, straightforward use of CORBA within HAHTsite applications is to provide a Web front-end for data from enterprise CORBA applications. Such data might be a customer s order information, normally residing on a mainframe. In this case, the HAHTsite Application Server runs code that acts as a CORBA client, connecting to a CORBA server object outside of HAHTsite. 315

337 Chapter 14: HAHTsite CORBA Capabilities Example: Building a HAHTsite CORBA client Imagine a legacy system containing a database with customer names and addresses, with access keyed to an account number. Typically, if the system is wrapped using CORBA, an IDL file will already exist describing the interfaces exposed by the system. In our simple example, the IDL file might look like this: Java module CustomerDB { interface Customer { attribute string last_name; attribute string first_name; attribute string address1; attribute string address2; }; interface DB { Customer getcustomerfromacct(in string account); string getinfobanner(); }; }; In practice, the IDL file would be much larger than the one defined here, but somewhere in it would be fields like the name and address for a customer, and a method to get the customer object from the database. Imagine a simple HAHTsite project containing a single Web page that allows the user to type in the account number and have the customer name and address displayed on the page. 316

338 Chapter 14: HAHTsite CORBA Capabilities Initialization of the CORBA ORB in the client can occur at any time; a convenient place to put the CORBA code is in Application.onSessionStart. All you have to do at this point is to bind to the server object. The Java application might contain code similar to this: Java // Make customer_database available through Application CustomerDB.DB customer_database; public void onsessionstart(com.haht.project.sessionevent anevent) { try { // Initialize the ORB org.omg.corba.orb orb = org.omg.corba.orb.init(); // Create the DB object - Example1 is the name of the // database server customer_database = CustomerDB.DBHelper.bind("Example1"); } catch(org.omg.corba.systemexception e) { System.err.println(e); } } Normally, one would probably obtain the customer account number as an input on the Web page this can be done via JavaScript or from an applet. In this example, you might simply generate a random account number from a list of available ones. The code to do this is in the application as well. Java public java.lang.string getrandomacct() { java.lang.string account_numbers[] = {"A09133F6", "B72553Z9", "C29943I7", "D28473W2", "E27723E6", "F23884K8", "G23847B2", "H23847O6", "I23984O2", "J29348W9", "K84724Z3", "L99283F9", "M73624G6", "N22731A1", "O88247Y2", "P83472P1", "Q24257Z0", "R82634D1", "S23523S9", "T23487U6"}; Random random = new Random(); int randval = random.nextint(); if (randval < 0) randval = -randval; randval = randval % account_numbers.length; return account_numbers[randval]; } 317

339 Chapter 14: HAHTsite CORBA Capabilities In order to get the information on the page, you place a server-side statement in the page. Java // First, print out today s banner from the database server Application app = com.haht.haht.getapplication(); out.println(app.customer_database.getbanner()+"</p><pre>"); out.println(app.getrandomacct()); out.println(app.customer_database.getname()); out.println(app.customer_database.getaddress1()); out.println(app.customer_database.getaddress2()+"</pre><p>"); Assuming the HAHTsite Application Server is running, and that the example CORBA server and Smart Agent are running, the first read of the page in this project will cause the session to be initiated, calling the CORBA client initialization code. Each read of the page will use the reference to the customer database to get the customer information, placing the information into the page. HAHTsite as a traditional CORBA server HAHTsite applications can also act as CORBA servers. Using CORBA, server-side applications can make callbacks into client applets, or send events that clients are registered to receive so that clients can be notified of changes in application status without requiring any action by the user or the overhead of polling by the applet. There are two basic methods that may be used to initiate a CORBA server within the HAHTsite Application Server. The traditional method discussed in this section follows the standard CORBA paradigm where the CORBA server is started by the HAHTsite application, initializing its objects. CORBA clients bind to objects in this server using a well-known name via the Naming Service or Smart Agent. The other method, in which the CORBA server uses the capabilities of a HAHTsite session, is discussed in CORBA and the HAHTsite Server Object Model on page

340 Chapter 14: HAHTsite CORBA Capabilities CORBA servers written in this traditional fashion are identical to everyday CORBA servers, with a few exceptions: The CORBA server doesn t have a main method, since it s started in the HAHTsite application in the Session.onStart method. You can use the HAHTsite IDE to build and publish the server. Server control is handled via the HAHTsite Application Server administration. The CORBA server inherits automatic restart and failover capabilities by running as part of the HAHTsite application. Like most simple CORBA systems, many clients bind to a single server object. Clients can be applets, CORBA client applications, or any CORBA-enabled HAHTsite applications. Example: Using CORBA to hold HAHTsite global state A simple use for a CORBA server running in HAHTsite is the storage of information to be shared between multiple invocations of the HAHTsite application. Such a server might store long-term user information, or cross-project data, acting as a service object. Here, both the CORBA server and client are running as applications in the HAHTsite Application Server. Because of CORBA, whether the client and server are located on the same Application Server is not important. This client looks essentially like the one in the previous example. Here, the server simply acts as a time accumulator for storing numbers of minutes on a per-customer basis. The IDL file is shown below. 319

341 Chapter 14: HAHTsite CORBA Capabilities Java module ServerStats { interface TimeRecord { void addminutes(in string user, in long minutes); void resetminutes(in string user); long getminutes(in string user); }; }; When you implement this interface in the server, you must follow certain naming conventions and put your source files in the correct folder. First, create a subfolder in the Packages folder and give it the name of your module. Then put your source files in this subfolder, and give them names of the form interfacenameimpl.java. For example, the source code for the TimeRecordImpl class should be placed in TimeRecordImpl.java. The client code also looks similar that shown in the last example. Java public void onsessionstart(com.haht.project.sessionevent anevent) { // Initialize the ORB org.omg.corba.orb orb = org.omg.corba.orb.init(); // Bind to the Superglobal time record ServerStats.TimeRecord record = ServerStats.TimeRecord.bind(orb, "Example2"); // Get the number of minutes of usage for this user from the // user long minutes = record.getminutes(user_id); // Get the customer information from the Database } Put the CORBA server part in the application s onsessionstart routine, and create the new TimeRecord class that implements the IDL interface: 320

342 Chapter 14: HAHTsite CORBA Capabilities Java public void onsessionstart(com.haht.project.sessionevent anevent) { orb = org.omg.corba.orb.init(); boa = orb.boa_init(); timerecord = new TimeRecordImpl("Example2"); boa.obj_is_ready(timerecord); } To start this CORBA server, you should configure the Applications Server to run the CORBA server as a service when a particular Server Group is started. For information on performing this configuration, see Chapter 3 in the HAHTsite Application Server Administration Guide. Note - You should not run the CORBA server and a HAHTsite application that is a client of that server in the same server process. A simple way to prevent this from happening is to establish a Server Group dedicated running to CORBA-server services. One other point. By default, a CORBA service can time out. You can prevent this from happening by setting the server s timeout value to -1. CORBA and the HAHTsite Server Object Model In addition to the simple CORBA clients and server discussed so far, it s possible to create CORBA servers that provide clients with access to HAHTsite Server Object Model objects and clients that take advantage of those services. The following subsections discuss this type of client and server further. Using the HAHTsite Server Object Model in a HAHTsite CORBA server HAHTsite as a traditional CORBA server on page 318 discussed one type of CORBA server. A second type of CORBA server may be written by using the capabilities of the HAHTsite session. Such a session-oriented CORBA server differs from the type described earlier in that it is initiated as part of a 321

343 Chapter 14: HAHTsite CORBA Capabilities HAHTsite session. Since each session has its own private set of objects, each CORBA server created in this manner has an independent set of objects as well. A CORBA server constructed in this fashion may be started in two ways. The initial HTTP reference to a page representing this session will cause the session to be invoked via the standard hsrun mechanism. The second method allows a CORBA client to initiate the session through use of a predefined ServerGroup object. You must include an IDL file describing the CORBA interface for each Java class you wish to expose via CORBA. If the session is to be accessible from CORBA, the project property must be set to indicate that the Session object is to be exposed as a CORBA object whenever a session of the application is initiated. When a method in a Java class in a HAHTsite application is invoked via CORBA, it is not running a HAHTsite dynamic page, and therefore does not have access to the HAHTsite Page, Request, and Response objects. However, it could have access to the Application and Session objects if they were passed to the object as arguments of a method. The methods of the Session class shown below enable you to register a server object as a visible CORBA object and to deactivate a CORBA object. Method Corba_obj_is_ready Corba_deactivate_obj Description Call this instead of obj_is_ready on the BOA, and the session will manage the object, deactivating it when the session is done. It makes calls to initialize the ORB and BOA the first time it is called within an application. This method removes the object from control of the session. Accessing the HAHTsite Server Object Model from a CORBA client A CORBA client of any type can reference the HAHTsite Application, Session, and ServerGroup classes of a HAHTsite CORBA server as CORBA objects. The set of methods available to perform on these objects from a CORBA application is defined in terms of CORBA IDL. It can be compiled into applications in any CORBA-supported language. The IDL describing the methods and classes available to CORBA programs resides in the file IDEInstallDir\scripts\HSCorbaInterface.idl. 322

344 Chapter 14: HAHTsite CORBA Capabilities HSCorbaInterface.idl module com { module haht { module corba { interface Application { string getname(); void writelog ( in string amessage); Object getcorbaobject( in string varname); string getstring( in string varname); void putstring( in string varname, in string varvalue); void remove( in string varname); void lock(); void unlock(); }; interface Session { string getstateid(); string getservergroupname(); string gethostname(); string createpageurl( in string aurl, in string asubsitename); string createmapurl( in string aurl, in string asubsitename); string createfileurl( in string aurl, in string asubsitename); 323

345 Chapter 14: HAHTsite CORBA Capabilities HSCorbaInterface.idl }; string createstaticurl( in string aurl, in string asubsitename); string geturl( in string projectid, in string defaultstr, in string querystr); string getstaticurl(); boolean hasprivilege( in string aprivilege); Object getcorbaobject( in string varname); string getstring( in string varname); void putstring( in string varname, in string varvalue); void remove( in string varname); void lock(); void unlock(); void setusername( in string ausername); string getusername(); void keepalive(); void settimeout( in long Timeout); long gettimeout(); Application getcorbaapplication(); }; }; }; interface ServerGroup { Session createapplicationsession(in string ApplicationPath); }; 324

346 Chapter 14: HAHTsite CORBA Capabilities These interfaces contain a subset of the methods available in the analogous classes in the Server Object Model. The behavior of the methods described in the interfaces is identical to their counterparts in the com.haht.project package. Client/server communication The com.haht.project.session and com.haht.project.application classes define a few additional CORBA-related methods. These methods facilitate client/server communication. Method getcorbaapplication getcorbaobject put putstring getstring Description returns the Application object that has been exposed to CORBA. This convenience function allows a CORBA client to get a reference to the Application object from the Session reference. returns a handle to a CORBA object. Can be called in the client to obtain a reference to a CORBA server object (posted with the put command) without having to bind the object in the server. posts an arbitrary Java object (in this case, a CORBA object) associated with a name. This object can be retrieved from the client side. posts a Java String associated with a name returns a string posted with the putstring command By using these interfaces, CORBA applications can pass CORBA objects between the client and server without having to contact the Naming Service or SmartAgent. CORBA must be enabled in the project for these routines to work properly. Example: Using CORBA in a session initiated via HTTP CORBA can be used as a convenient way to set up a non-http connection between the Web client and the Application Server. See the figure below. 325

347 Chapter 14: HAHTsite CORBA Capabilities Once the HAHTsite application is initiated, a Java applet on the dynamic page can be connected back to the Session object via CORBA by performing the following steps: 1 The dynamic HTML page should use the Session.getStateId method to obtain the session s State ID. 2 JavaScript on the page can pass the state ID as an argument to a method of an applet on the page. 3 The applet can make the CORBA calls to initialize the ORB and bind to the Session object on the server. This returns an object reference to the application s session object. The code for the applet method would look something like: Java public void connecttosession(string StateId) { // Initialize the ORB org.omg.corba.orb orb = org.omg.corba.orb.init(this, null); // Bind to the Session Session session = com.haht.corba.sessionhelper.bind(orb,stateid); // Retrieve a CORBA object for use in the applet MyCorbaObject my_corba_object = (MyCorbaObject)session.getCorbaObject("my_corba_object"); // Get another object using the bind() technique MyOtherCorbaObject my_other_corba_object = MyOtherCorbaObjectHelper.bind (orb,"my_other_corba_object");

348 Chapter 14: HAHTsite CORBA Capabilities Example: Initiating a HAHTsite application session with CORBA A HAHTsite application session can also be initiated by a CORBA client. See the figure below. In order to accomplish this, the client must follow the steps: 1 Initialize the CORBA ORB and bind to the ServerGroup object. This requires you to know the name of the ServerGroup object. Usually, the name is generated during the HAHTsite installation process. It should be available from the HAHTsite system administrator. 2 Invoke the createapplicationsession method on the ServerGroup object. This starts a session of the specified application and returns a CORBA reference to the new application Session object. The code for such a CORBA client might contain something like: 327

349 Chapter 14: HAHTsite CORBA Capabilities Java public void createsession() { // Initialize the ORB org.omg. CORBA.ORB orb = org.omg.corba.orb.init(args, null); // Bind to the HAHTsite ServerGroup object com.haht.corba.servergroup servergroup = com.haht.corba.servergrouphelper.bind(orb, "webapps"); // Create the appliation session and get a reference to it Project1.HAHTSession session = servergroup.createapplicationsession ("Project1/Project1.html");... } Note - In order for this method to work, the HAHTsite system administrator must enable application sessions to be started using CORBA. By default, this capability is disabled, preventing a session from being initiated. Other Information This section presents some miscellaneous information about HAHTsite s CORBA capabilities. It discusses: using the VisiBroker ORB with other ORBs using CORBA in HAHTtalk Basic projects installing and configuring VisiBroker VisiBroker s SmartAgent and the CORBA Naming Service VisiBroker s GateKeeper software Interoperability with other ORBS HAHTsite applications built using VisiBroker can connect to and exchange data with applications built using any CORBA 2.0 ORB. The communication protocol used to connect the ORBS (Internet Inter-Object Protocol - IIOP) is standardized and allows interworking between different vendors ORBs. The VisiBroker IDL compiler idl2java must be run with the -strict 328

350 Chapter 14: HAHTsite CORBA Capabilities command-line option in order to generate stubs that will work with other ORBs. Using CORBA with HAHTtalk Basic Although CORBA services are not directly available from HAHTtalk BASIC, it is still possible to link with CORBA-enabled systems from these applications. Using the CreateJavaObject call in HAHTtalk, you can create a Java class that can in turn make CORBA calls exactly as described above. Using this technique, it is possible to make CORBA clients and servers in HAHTtalk Basic applications. VisiBroker installation and configuration The setup for the Application Server allows you to install VisiBroker for Java as a custom installation option. In order for HAHTsite applications to act as CORBA clients, VisiBroker for Java must be installed on the Background Host. In a distributed configuration, it must be installed on each Background Host, although the osagent (if used) need only run on one Background Host. If HAHTsite applications are to be started as CORBA servers by external CORBA clients, VisiBroker for Java must also be installed on each of the Foreground Hosts. By default, the VisiBroker runtime.jar files are included on the System Java Classpath for the Server Group. They are required for CORBA operation and should not be removed from the classpath. VisiBroker SmartAgent and the CORBA Naming Service The VisiBroker for Java software includes the Inprise implementation of the standard CORBA Naming Service. It also includes a simple object registry called osagent or SmartAgent. Licenses for both are included with HAHTsite. The HAHTsite Application Server allows the use of either Naming Service or SmartAgent, but the HAHTsite Server Object Model objects such as Application and Session are only available to the programmer through the SmartAgent. VisiBroker GateKeeper The Java sandbox security model allows an unsigned Java applet to connect only to the server from which it was invoked. The VisiBroker GateKeeper software permits applets to connect to other servers. If your HAHTsite system is configured with separate Foreground and Background Hosts, you will need 329

351 Chapter 14: HAHTsite CORBA Capabilities to employ the VisiBroker GateKeeper to allow CORBA connection between CORBA-enabled applets and the HAHTsite servers. This is true even if no firewall exists between the applets and application. The VisiBroker GateKeeper software and license are included with HAHTsite. References These two documents are available with the VisiBroker software and are also available for download from the Inprise Web page: VisiBroker for Java Programmer s Guide VisiBroker for Java Reference Manual 330

352 Debugging Server-side Code 15 Introduction Requirements for debugging Starting a debugging session To start a debugging session To begin debugging at a static page To stop a debugging session Debugging a code page Executing code in the debugger Single-stepping Procedure-stepping Using breakpoints The debug windows Debug output panel Variable window Watch window Call Stack window Threads window

353 Chapter 15: Debugging Server-side Code Introduction This chapter explains how to use the IDE/IP debugger to find errors in HAHTsite server-side code. Debugging of both Java and HAHTtalk Basic projects is supported. In addition to debugging locally, in the development environment, HAHTsite supports remote debugging of dynamic Web pages, allowing you to debug dynamically created Web pages in the deployed environment. Requirements for debugging You can debug a project s dynamic code pages (server-side code) running in the HAHTsite Application Server from any Internet-connected client, using the IDE/IP. Projects can also be debugged locally in the Application Server: Developer Edition. The following requirements must be met: The pages to be debugged must have been published. The Application Server (or the Application Server: Developer Edition) must be running. The Application Server must have at least one debug process enabled. In the Application Server, accounts and privileges must be set up to permit debugging and to control the number of active debug sessions allowed. You must have an account and debugging privileges on the server machine to start a debug session. When you are debugging using the Application Server: Developer Edition, account privileges are not required. For information on enabling debug processes and administering accounts and privileges, refer to the HAHTsite Application Server Administration Guide, Chapter 3, Performing Administrative Tasks. Java projects must have been built in debug mode. Note - Debugging is not supported for server-side Java code in a HAHTtalk Basic project. The debugger treats invocations of Java methods as a single HAHTtalk Basic statement. 332

354 Chapter 15: Debugging Server-side Code A special case: debugging HAHTtalk Basic stand-alone programs A HAHTtalk Basic code page with a main subroutine can be debugged without being published. This type of code page does not represent a dynamic HTML page, but is a stand-alone program. Starting a debugging session Debugging sessions may be run against a local site, using the Application Server: Developer Edition during project development. Debugging sessions may also be run against a remote site, using the Application Server. This configuration allows debugging in a deployment situation. To start a debugging session 1 Open the project that you want to debug. 2 Select Project > Debug From Site, or select the Start button from the Code and Scripts Tools toolbar. The Debug From Site dialog appears. 333

355 Chapter 15: Debugging Server-side Code 3 Enter your user name, domain and password. If the Application Server is installed on a UNIX system, leave the domain field blank. If Allow Anonymous Debug is set on the Application Server, or you are using the Application Server: Developer Edition, you can leave all three fields blank. The Application Server: Developer Edition does not support authentication. 4 Specify an unused IP port on your system. The debugger uses two consecutive ports (7000 and 7001 are the defaults.) If you are accessing the Application Server through a firewall, be sure to specify a port that is configured to route back to your system. 5 Select the page to use as a starting point for the debug session. You can select any page in the project. 6 Click OK. As the IDE establishes a connection with the server, status messages are displayed in the Output window. To begin debugging at a static page 1 If you select a static page as the start page, the browser displays a page that prompts you to start the debugging process. The URL of the page indicates the page is being run by a debug process of the Application Server. 334

356 Chapter 15: Debugging Server-side Code 2 Click the link labeled Click Here to Debug to start the debugging session. Clicking on this link notifies the Application Server to start the debugger when a dynamic page is executed. The static page selected as the starting point for the debug session will be displayed in the browser. 3 Navigate through the Web site to the dynamic page that you want to debug. When a dynamic page is requested by the browser, the execution of the Application Server program is paused immediately before the first statement of the code page. To stop a debugging session While in a debug session, click the End button on the Code and Scripts Tools toolbar. Tip - If the End button is activated, you are in a debug session. If the End button is not activated, you are not in a debug session. When the buttons to single-step and procedure-step are active, you are in a debugging session and program execution is paused. If you are in a debug session and the single-step and procedure-step buttons are not activated, the program is running. 335

357 Chapter 15: Debugging Server-side Code Debugging a code page The Server-side Code view of the HTML editor displays the code used to generate the HTML page. In a debugging session, you can run the application until a breakpoint is encountered as well as step through the code as it is executed. When you step through a code page, the HTML editor displays a yellow arrow to the left of the next line of code that will be executed.the debugger allows you to step through code pages using single-step, using procedure-step and by setting breakpoints. The debug commands are available in the Debug menu on the main toolbar. The Debug menu is visible only when the HTML editor is in the Server-side Code view, when you re viewing a code page, and when a debug session is active. Each of the commands in the Debug menu is also represented by a button on the Code and Scripts Tools toolbar.. Executing code in the debugger When a debugging session is started, (see Starting a debugging session on page 333) the execution of the Application Server program is paused immediately before the first statement of the code page of the first dynamic page is executed. The Debug > Start command will cause the application to continue executing statements until one of the following conditions occurs: a statement having a breakpoint is encountered, the code page is completed and sent to the browser, or a run-time error in the code is encountered. If the page is completed, the page will be visible in the browser. The debugging session will be continued when another dynamic page is requested by the 336

358 Chapter 15: Debugging Server-side Code browser. If any of the other conditions occur, the application execution pauses and the debug windows will contain updated information about the state of the application. Note - The debugger will not automatically pause the application at the beginning of each dynamic page it encounters. Only the first dynamic page encountered in the session will be paused, and only for the first time through that page. To cause the debugger to pause the application at the beginning of a dynamic page, set a breakpoint at the beginning of that page. To start code execution While in a debug session, click the Start button on the Code and Script Tools toolbar. Single-stepping Single-stepping is the process of executing one statement at a time. You can see the effect of each statement by looking at the browser window, the Serverside Code window, and the Variable, Watch, Call Stack and Threads windows. When a method or subroutine is encountered in a statement, the single-step command steps into the method or subroutine, following the execution path of the program. Note - The debugger does not step into code whose source code is not part of the published project. For instance, the source code for the Application Server and language libraries are not accessible by the debugger. To single-step through code While in a debug session, click the Single-step button on the Code and Script Tools toolbar. To step out of a method or subroutine 1 In the Call Stack window, double-click on the previous call level. This will be the line immediately below the top line. 2 Set a breakpoint on the statement following the current statement in the calling method or subroutine, as indicated by a yellow arrow. 3 Click the Start button. The program execution will continue through the method or subroutine and stop at the statement after the method or subroutine has returned. 337

359 Chapter 15: Debugging Server-side Code Procedure-stepping Procedure-stepping is like single-stepping, except that you step over methods or subroutines. The Procedure-step command executes a statement containing a method or subroutine as a unit, then steps to the next statement in the current method or subroutine. To use procedure-stepping While in a debug session, click the Procedure-step button on the Code and Script Tools toolbar. Using breakpoints Breakpoints pause an application before the line of code that the breakpoint is set on is executed. Variables and the call stack can be examined when the application is paused. Threads can also be monitored in Java projects. After pausing at a breakpoint, you can continue program execution by clicking on the start button, or you can step through and monitor critical sections of the code. When you are in a debugging session, you can set or remove breakpoints on any published dynamic page or code page in the project. Breakpoints can be set when the execution is paused in a dynamic page or when the Application Server is waiting for browser input between dynamic pages. When you are not in a debugging session, you can set or remove breakpoints at any location in the server-side code. Breakpoints which are set while not in a debugging session will not take effect in the next debugging session. Pages do not need to be re-published for breakpoints to take effect. Breakpoints are stored in the project and are remembered between IDE/IP sessions. To set or remove breakpoints 1 In the Server-side Code view of the HTML editor, position the cursor on a statement to set or remove a breakpoint. 2 From the main toolbar, select Debug > Toggle Break Point, or click the Toggle Breakpoint button on the Code toolbar. When a line has a breakpoint, a red circle is displayed next to the line. The following example shows a subroutine that has one breakpoint, indicated by a (red) circle to the left of the statement. The (yellow) arrow indicates the next line of code to be executed. 338

360 Chapter 15: Debugging Server-side Code Once breakpoints are set in the code, select Debug > Start, or click the Start button on the Code and Scripts toolbar to cause the program to continue execution until it reaches a statement containing a breakpoint. Note - In a debugging session, you can edit the source code using the Server-side Code view of the HTML editor, and save your changes. You must stop the current debug session, then build and publish the pages containing the changes before your edits will take effect. As a convenient way to manage multiple breakpoints, the Breakpoint Manager allows you to remove selected breakpoints, and remove, enable and disable all breakpoints in a single operation. To use the Breakpoint Manager From the main toolbar, select Edit > Breakpoints... The Breakpoint Manager dialog appears. 339

361 Chapter 15: Debugging Server-side Code The Breakpoint Manager dialog displays a list of all breakpoints in the project.check marks in the checkboxes next to the breakpoints indicate enabled breakpoints.. Button Action Remove RemoveAll EnableAll DisableAll Removes the breakpoints that have been selected. Selected breakpoints are highlighted. Removes all breakpoints. Turns all breakpoints on. Check marks in the checkboxes indicate enabled breakpoints. Turns all breakpoints off. The breakpoints will still exist, but will not cause the program to pause at that point. Shortcut - You can also remove all breakpoints by selecting Debug > Clear All Break Points from the main toolbar. The debug windows When the Application Server encounters a dynamic page during a debug session, the HTML editor switches to the Server-side Code view and displays the code for that page. Several other windows provide debug information and control during a debug session. Output window, Debug panel Variable window Watch window Threads window The visibility of these windows is controlled through the View menu on the main tool bar during the debug session. If the windows are visible, the IDE/IP switches to the Debug panel of the Output window and opens the Watch, Call Stack, Variable and Threads windows. The Threads window is only used in debugging Java projects. These windows are updated each time the program execution is paused. 340

362 Chapter 15: Debugging Server-side Code Debug output panel The Debug panel of the Output window displays a trace of the server requests and responses during the debug session. Click on the plus signs (+) to expand the messages. Information displayed for each HTTP request includes the environment variable settings and the HTTP response stream created for the page. This window is updated each time the program is paused after hitting a breakpoint. Note - Informational messages from the debugger are sent to the Output panel of this window during the debug session. Variable window The Locals panel of the Variables window displays all local variables and their values. This window is updated each time the program execution is paused at a breakpoint. The values of these variables can be modified at runtime by changing the data in the value field of this variable. Variable arrays, structures and Java objects in this window can be expanded by clicking on the (+) next to the name. Individual values of the fields can be viewed and/or modified. 341

363 Chapter 15: Debugging Server-side Code In Java projects, this panel of the Variable window is used to display the class instance that contains the current statement. When you re debugging Java projects, the Variable window shows the superclass hierarchy of all objects and displays the member variables for the class and the superclasses. The values in the panel can be modified in the same manner as the local variables. Note - The value of certain variables, such as pointers, cannot be modified. To modify a local variable 1 Click on a variable name in the Locals panel of the Variable window. The Modify Variable dialog appears. 2 Type the new value of the variable in the Value field. 3 Optionally, you can check the box labeled Add to watch window. If this option is selected, the variable will be added to the list of watched variables in the watch window. 342

364 Chapter 15: Debugging Server-side Code 4 Click the OK button. Shortcut - Variable values can also be changed by simply clicking on the value in the Variable window and typing in the new value. Watch window The Watch window allows you to select variables that you want to monitor during a debug session. The Watch window displays the name and value of all of the variables you are currently watching. In HAHTtalk Basic projects, the watch window displays the value of the variable s scope. The value of watched variables can also be changed from the watch window (see To modify a local variable on page 342.) To add a watch variable 1 From the main toolbar, select Debug > Add Watch, or click the Add Watch button on the Code and Scripts Tools toolbar. The Add Watch dialog appears. 2 Type the name of the variable into the Variable Name field. Shortcut - You can drag-and-drop variables into the watch window from the Server-side Code view of the HTML editor. 343

365 Chapter 15: Debugging Server-side Code In addition, you can substitute a different variable in the watch list by selecting Debug > Edit Watch, and you can change the value of a watched variable by selecting Debug > Modify Watch. To remove a watched variable Select the variable from the list in the Watch window and press Delete. In Basic projects, the Watch window has a context field. The context field controls the context or scope used to determine the value of the variable. The any context in the Basic project watches follows the Basic scoping rules. Selecting another context displays variables using that context. Watches on Java variables always follow the scoping rules of Java. Watches remain set between debugging sessions, but do not persist across invocations of the IDE/IP. Call Stack window The Call Stack window is used to trace the execution of a page as it enters and returns from methods or subroutines. The Call Stack window displays a list of all of the methods or subroutines that the application has entered but not returned to the invoking method or subroutine. The window displays the earliest active subroutine at the bottom of the list and adds subsequent calls to the top of the list. You can double-click any entry in the Call Stack window to change the context of the other windows to the display values at that call level. The selected call level is indicated in the Call Stack window by a yellow triangle. The variables in the Watch and Variable window reflect their state at the selected call level. The Server-side Code editor marks the corresponding execution point at the selected call level with a yellow arrow. Shortcut - To make the Call Stack Window visible, click the Call Stack button. 344

366 Chapter 15: Debugging Server-side Code Threads window The Threads window is only used when debugging a Java project. When a HAHTsite Basic project is being debugged, this window is not available. When a program is paused, the Threads window contains the list of active threads, their names, and the class and method the thread is in at the current execution point. The Threads window controls display context like the Call Stack window. When you click on a thread, the Server-side Code window displays the source code for the location in that thread. All windows are updated to contain information in the context of the call stack for the selected thread. If you click on a thread that has no available source code to display, the Thread window indicates that the current line number is zero and all the windows are updated, except for the code window. 345

367 Chapter 15: Debugging Server-side Code 346

368 HAHTsite 3.x WebApp Methods and Properties A Introduction WebApp properties WebApp methods Pseudo-methods

369 Appendix A: HAHTsite 3.x WebApp Methods and Properties Introduction This appendix lists the WebApp properties and methods (from HAHTsite 3.x) and their equivalent functionality in the HAHTsite Server Object Model. The WebApp properties and methods are still supported for legacy code and can be intermixed with Server Object Model classes and methods. However, for new projects it is highly recommended that you use only the HAHTsite Server Object Model. WebApp properties This table lists the WebApp properties from HAHTsite 3.x and the equivalent methods in the HAHTsite Server Object Model. WebApp Server Object Model Property Definition Class Method DirName DynamicURL HAHTMapPrefix HAHTPagePrefix The directory containing the HAHTtalk Basic executable program. The root of this path is the configured application root directory, so this path does not typically represent a real operating system path. The URL of the Web server s CGI-BIN directory. The URL prefix-string for references to dynamic image maps on the default subsite. The URL prefix-string for references to dynamic pages on the default subsite. Application Application Session Session getdirname getappdata (index, "DynamicURL") createmapurl("") createpageurl (pagename, subsitename) 348

370 Appendix A: HAHTsite 3.x WebApp Methods and Properties WebApp Hostname HTXName InHeaders NewApp PageName PathName ServerName The hostname of the current machine The simple name (without a suffix) of the executable file. Whether or not the page being generated is still in the HTTP headers section. Whether or not this is a new instance of the application. The entry-point name of the currently executing dynamic page. The combination of DirName and HTXName. The name of the server group serving the application. Session Application Response Session Page Application Session gethostname getname inheaders isnewapp getname getpathname getservergroupname StateId The StateId value. Session getstateid StaticROOT StaticURL Timeout Operating systemdependent path to the Web server s staticpage directory on the default subsite. URL to the Web server s static-page directory on the default subsite. The application timeout value in seconds. Server Object Model Property Definition Class Method Application Session Session getstaticroot and getappdata(index, "StaticROOT") getstaticurl and getappdata(index, "StaticURL") gettimeout 349

371 Appendix A: HAHTsite 3.x WebApp Methods and Properties WebApp UserROOT UsingCookies Operating-system dependent path to the Web server s initial working directory on the default subsite. Whether or not the application was published to place the StateId into cookies. Server Object Model Property Definition Class Method Application Application getuserroot and getappdata(index, "UserROOT") isusingcookies WebApp methods This table lists the methods of the WebApp object and the corresponding method in the HAHTsite Server Object Model.. WebApp Server Object Model Method Definition Class Method EndHeaders Environ$ GetAppData GetMapPrefix$ GetPagePrefix$ GetStaticURL$ GetSubSiteCount Writes the End-of- Headers mark and sets InHeaders to False. Returns the value of an environment variable. Returns information about the application. Returns the URL for an image map Returns the URL for a dynamic page Returns the URL of the Web server s static-page directory Returns the number of subsites defined for the application. Response Request endheaders getservervariable Application getappdata Session Session Session createmapurl createpageurl createstaticurl Application getsubsitecount 350

372 Appendix A: HAHTsite 3.x WebApp Methods and Properties GetSubSite$ GetURL$ HeaderField HeaderLine HeaderMark URLAttachment$ URLAttachmentCount Returns the name of the subsite associated with the value of the (zero-based) Index argument. Locates a project item by its unique ProjectID and returns a string with either a full or relative URL for that item. Writes the string as a partial header line. Writes the string as a complete header line, supplying the terminating <CR><LF> pair. Writes the <CR><LF> line mark after a series of HeaderField calls. Returns the name of the temporary file used for the attachment associated with the URL field name String. Returns the total number of attachments. URLAttachmentExists Returns True or False, indicating whether an attachment exists for the URL field name String. URLAttachmentType$ WebApp Returns the Content- Type of the attachment associated with the URL field name "String." Application getsubsite Session Response Request Request Request Request Server Object Model Method Definition Class Method geturl n.a. addheaderline n.a. geturlattachment geturlattachmentcount geturlattachmentexist s geturlattachmenttype 351

373 Appendix A: HAHTsite 3.x WebApp Methods and Properties URLField$ URLFieldCount URLFieldExists WhoAmI$ WhoCalledMe$ WriteLog WebApp Returns the value of a field on the URL or in a form. Returns the total number of URL fields. Tests whether the named field is in the URL. Returns the name of the current page or HAHTtalk Basic subroutine. Returns the name of the page or HAHTtalk Basic subroutine that called the object on which the method is located ( me"). Writes a string to the Application Server s log file. Request Request Request Session Session Server Object Model Method Definition Class Method geturlfield geturlfieldcount geturlfieldexists whoami whocalledme Application writelog Pseudo-methods Pseudo-methods are place-holders that you can override with a function or subroutine. This table summarizes the WebApp pseudo-methods and lists the corresponding methods in HAHTsite s Server Object Model. If a project calls both the "old" Webapp pseudo-method and the new Server Object Model pseudo-method, the newer method will run first. (Note that these pseudomethods apply only to HAHTtalk projects. Java projects should use the Session class s onstart and onend methods.) HahtSessionOnStart should be declared as a function returning a boolean value (for success or failure). HahtSessionOnEnd should be declared as a subroutine. Neither routine takes any arguments. 352

374 Appendix A: HAHTsite 3.x WebApp Methods and Properties WebApp WebApp Server Object Model Pseudo-method Definition Pseudo-method Initiate (WebApp_Initiate) TimeUp (WebApp_TimeUp) Terminate (WebApp_Terminate) The session was just initiated. The Timeout value has elapsed. The session is about to be terminated. HahtSessionOnStart No equivalent. Do not use. HahtSessionOnEnd 353

375 Appendix A: HAHTsite 3.x WebApp Methods and Properties 354

376 HAHTsite 3.x Data Management B Introduction DataSets and data agents Accessing and changing DataSet properties at runtime DataSet control functions Writing user-defined DataSet functions Accessing and changing form-control properties at runtime Connection-manager functions

377 Appendix B: HAHTsite 3.x Data Management Introduction This appendix summarizes the ways in which programming database applications differs between HAHTsite 3.x and HAHTsite 4.0. In general, the objects with which you interacted in HAHTsite 3.x DataSets, form controls, and the connection manager are now represented by classes in the Server Object Model (or by ActiveX Data Object classes). The correspondence between a 3.x object and a Server Object Model object is not always one-to-one, and the 4.0 methods may behave differently than their 3.x counterparts. Note, too, that the HAHTsite 4.0 release offers much greater functionality than is represented in this appendix. The 3.x properties and functions will continue to be supported in legacy projects, but any new projects should be developed using the Server Object Model. You can mix both models within the same project, but not on the same page. DataSets and data agents DataSets in HAHTsite 3.x have been replaced by data agents. These objects are similar; however, data agents are only responsible for populating form fields on a page with data read from an ADO recordset. Separate command handlers perform the actions associated with form buttons. The sections below explain how the DataSet programming tasks covered in the 3.x documentation are handled in HAHTsite 4.0. Accessing and changing DataSet properties at runtime HAHTsite 3.x maintained several DataSet record structures DataSet_Widget, DataSet_RecordSet, and DataSet_BoundWidget and enabled you to set properties of these structures. These record structures are not used in HAHTsite 4.0. The table below guides you to the Server Object Model classes that contain data similar to that stored in the 3.x record structures. Record structure DataSet_Widget The properties of this structure enabled you set such attributes as the DataSet s name, filter, and default action. Server Object Model classes DataAgent This class has member variables that give you access to similar data. 356

378 Appendix B: HAHTsite 3.x Data Management Record structure DataSet_RecordSet The DynaSet property enabled you to read or write the name of the DataSet s dynaset. DataSet_BoundWidget The properties of this structure enabled you to read or change attributes of form controls bound to the DataSet. Server Object Model classes DataAgent You can get or set a data agent s recordset using the methods getrecordset and setrecordset. (To work with a recordset, you use methods of the ADO Recordset class.) FormField and its subclasses In HAHTsite 4.0, form fields are represented by subclasses of the SOM class FormField. You set form-field attributes using methods of these subclasses. (Note that some of the bound-widget properties you could read or set in 3.x are no longer applicable.) DataSet control functions HAHTsite 3.x provided a small set of DataSet-control functions. These functions and their 4.0 counterparts are listed in the table below. DataSet-control function DataSet_GetBoundWidgetIndex DataSet_GetBoundWidgetValue DataSet_SetBoundWidgetValue DataSet_Close Server Object Model classes This function does not have a counterpart in 4.0. Subclasses of FormField You get the value of a form field using the method getvalue, which is inherited from FormField. Subclasses of FormField You set the value of a form field using the method setvalue. DataAgent The close method closes all of a data agent s open resources. 357

379 Appendix B: HAHTsite 3.x Data Management Writing user-defined DataSet functions In HAHTsite 3.x, DataSets perform standard HAHTsite database actions (such as Insert) on behalf of a form button, and you have the option of overriding a standard event. In HAHTsite 4.0, the actions are performed by command handlers that are generated by HAHTsite. You have the option of modifying these command handlers by adding event handlers to the generated code. Accessing and changing form-control properties at runtime In HAHTsite 3.x, you could read and set properties of the following form controls: Text boxes Text areas Check boxes Radio buttons Combo boxes List boxes Static text HAHTsite maintained a set of record structures for each form control ControlName_Widget, ControlName_BoundWidget, ControlName_ExtAttr, and in some cases ControlName_List and you changed a form control s attributes using properties of these structures. In HAHTsite 4.0, form fields are represented by Server Object Model classes, and you modify the attributes of a form field using get and set methods. The table below shows the correspondence between the types of form fields and the relevant Server Object Model classes. Note - The FormField class is relevant in each case because FormField is the superclass of all the specific form-field classes, and all of these classes inherit methods from FormField. Form control Text box Server Object Model class Textbox 358

380 Appendix B: HAHTsite 3.x Data Management Form control Text area Check box Radio button Combo box List box Static text Server Object Model class TextArea Checkbox Radiobutton Combobox Listbox StaticText The Server Object Model also includes classes for form buttons (Button) and File Upload fields (FileUpload). Connection-manager functions HAHTsite 3.x provided a set of functions for working with the Connection Manager. In HAHTsite 4.0, the counterpart of the Connection Manager is an instance of the Server Object Model s DMConnectionManager class. The table maps the 3.x open- and close-connection functions to the appropriate methods of the DMConnectionManager class. Connection Manager functions GetConnection CloseConnection DMConnectionManager methods getsharedconnectionbyid getsharedconnectionbyname openconnection openprivateconnectionbyid openprivateconnectionbyname closeallconnections closeprivateconnection 359

381 Appendix B: HAHTsite 3.x Data Management 360

382 Code Examples C Calling a subroutine as a form action Modifying a command handler Writing a custom authentication class

383 Appendix C: Code Examples Calling a subroutine as a form action Calling a subroutine from a form on page 134 explains how to have your application invoke a Java method or HAHTtalk Basic subroutine when a form is submitted. The example presented in that section assumes that the user of the application enters the path to an image in a file-upload field. Then, when the form is submitted, a subroutine reads the filename from a URL and writes the contents of the file to a field in a database. The subroutine is shown below in both its Java and HAHTtalk Basic flavors. Java package FileUploadJava; import com.haht.*; import com.haht.project.*; import com.haht.ado.abstract.*; import java.io.*; class StuffAPictureInAccess extends Object implements HAHTPage { static final int BUFSIZE = 1024; public void run (Request arequest, Response aresponse) { // For success, failure HsMessage_Page mymsgpage = new HsMessage_Page(); // Check to see if they've sent the data // if (arequest.geturlfieldexists("txtname") && arequest.geturlattachmentexists("uplpicture")) { // Get shared connection, open NameAndPict table // to get recordset Connection myconn; try { 362

384 Appendix C: Code Examples Java myconn = Haht.getSession().getConnectionManager(). getsharedconnectionbyname("nameandpict"); } catch (com.haht.hahtexception e) { mymsgpage.seterrormessage ("Unable to open connection: " + e.tostring()); mymsgpage.run (arequest, aresponse); return; } Recordset myrs = new com.haht.ado.recordset(); if (myrs == null) { mymsgpage.seterrormessage ("Unable to create recordset"); mymsgpage.run (arequest, aresponse); return; } myrs.setactiveconnection(myconn); // So we can Insert/Update/Delete myrs.setcursortype (com.haht.ado.cursortypeenum.adopenkeyset); myrs.setlocktype (com.haht.ado.locktypeenum.adlockoptimistic); try { myrs.open("nameandpict"); } catch (java.lang.exception e) { mymsgpage.seterrormessage ("Opening NameAndPict table failed"); mymsgpage.run (arequest, aresponse); return; } 363

385 Appendix C: Code Examples Java // Get filename of uploaded image, open it, and // prepare to appendchunk it into the recordset // field. java.io.file picturefile = new java.io.file (Haht.getApplication().getUserRoot() + '/' + arequest.geturlattachment("uplpicture")); FileInputStream picturestream; Field picturefld; try { picturestream = new FileInputStream (picturefile); } catch (java.io.filenotfoundexception e) { mymsgpage.seterrormessage ("Unable to open uploaded file"); myrs.close(); mymsgpage.run (arequest, aresponse); return; } // Add new record to recordset to put picture in, // assign name to it, and get picture field to // append data to. myrs.addnew (); myrs.getfield("name").setstring (arequest.geturlfield("txtname")); picturefld = myrs.getfield("picture"); // Allocate a buffer and read until we're done // byte [] picturebuf = new byte[bufsize]; int nbytesread; int nbytestotal = 0; 364

386 Appendix C: Code Examples Java do { try { nbytesread = picturestream.read(picturebuf); nbytestotal += nbytesread; if (nbytesread > 0) { picturefld.appendchunk (picturebuf, nbytesread); } } catch (java.io.ioexception e) { mymsgpage.seterrormessage ("Error while reading file"); myrs.close(); mymsgpage.run (arequest, aresponse); try { picturestream.close(); } catch (java.io.ioexception e2) { } return; } } while (nbytesread > 0); // Finish inserting the record by updating the // recordset myrs.update(); 365

387 Appendix C: Code Examples Java // Close up shop, call Results page try { picturestream.close(); } catch (java.io.ioexception e) { } myrs.close(); } } mymsgpage.setmessage ("Copied " + String.valueOf(nBytesTotal) + " bytes to record for " + arequest.geturlfield("txtname")); mymsgpage.run (arequest, aresponse); } else { mymsgpage.seterrormessage ("Picture name or file missing"); mymsgpage.run (arequest, aresponse); } 366

388 Appendix C: Code Examples HAHTtalk Basic #include <SOMConstants.hbh> #include <ADOConstants.hbh> Const BLKSIZE = 1024 Public Sub StuffAPictureInAccess Dim myconnmgr As Object, mysession As Object Dim spicturefilename As String Dim arequest As Object Dim picturefld As ADODB.Field, namefld As ADODB.Field Dim fread As Long Dim flen As Long Dim nblksize As Long, nbytestotal As Long Dim sbuf As String Dim nullobj As Object Dim myrs As New ADODB.Recordset Dim myconn As ADODB.Connection ' ' Check to see if they've sent the data ' Set arequest = Haht.getRequest() Set nullobj = Nothing If (arequest.geturlfieldexists("txtname") _ And arequest.geturlattachmentexists("uplpicture")) Then ' ' Get shared connection, open NameAndPict table to ' get recordset ' Set myconn = getsharedconnectionbyname _ ("NameAndPicture") set myrs.activeconnection = myconn myrs.cursortype = adopenkeyset myrs.locktype = adlockoptimistic myrs.open "NameAndPict" 367

389 Appendix C: Code Examples HAHTtalk Basic ' ' Get filename of uploaded image, open file, and prepare ' to appendchunk image into the recordset field ' spicturefilename = HahtApplication.getUserRoot() & "/" & _ & arequest.geturlattachment("uplpicture") Set picturefld = myrs.fields("picture") Set namefld = myrs.fields("name") fread = FreeFile() Open spicturefilename for Binary Access Read As #fread ' ' Add new record to Recordset to put picture in, add ' data to it ' myrs.addnew namefld.value = arequest.geturlfield("txtname") flen = FileLen(sPictureFileName) nblksize = IIF(fLen < BLKSIZE, flen, BLKSIZE) sbuf = String$(nBlkSize, 0) nbytestotal = 0 While flen > 0 Get #fread,,sbuf nbytestotal = nbytestotal + nblksize picturefld.appendchunk sbuf flen = flen - nblksize If ( flen < nblksize ) AND ( flen > 0 ) Then nblksize = flen sbuf = String$(nBlkSize,0) End If Wend ' ' Close file, continue ' Close #fread myrs.update 368

390 Appendix C: Code Examples HAHTtalk Basic ' ' Close up shop, call Results page ' myrs.close Set myrs = Nothing Set myconn = Nothing Set myconnmgr = Nothing gmessagetext = "Copied " & CStr(nBytesTotal) & _ " to record for " & arequest.geturlfield("txtname") Set arequest = Nothing goto StuffAPictureInAccess_Exit Else gmessagetext ="Picture name or file missing" goto StuffAPictureInAccess_Exit End If StuffAPictureInAccess_Exit: HS_Message_Page Exit Sub StuffAPictureInAccess_Errors: ' Dump any errors we want to here gmessagetext = "Error " & Str$(Err) & " - " & Error & _ " occurred processing picture" Resume StuffAPictureInAccess_Exit End Sub 369

391 Appendix C: Code Examples Modifying a command handler This section presents an example of how you might customize a command handler s prebind method. Suppose that you have a form that contains a File Upload form field. When a user runs your application, he or she will enter the path to an image file in the File Upload text field. When the user clicks the Insert button, you want to take this pathname, open the image file, and write the contents of the file to a BLOB field in your database. (The record containing the image will also contain a picture name that you can use to identify the image.) Since HAHTsite doesn t generate code for inserting a large binary object into a database, you must add code similar to the following to a command handler to insert this object in your database. HAHTtalk Basic ' ' Get the filename of an uploaded image, open the file, ' and copy its contents into a record field that holds ' binary data. ' Dim arequest As Object Dim spicturefilename As String Dim picturefld As Object, namefld As Object Dim fread As Long Dim flen As Long Dim nblksize As Long Dim sbuf As String On Error GoTo onbind_errorhandler Set arequest = Haht.getRequest() spicturefilename = HahtApplication.getUserRoot() & "/" _ & arequest.geturlattachment("upload1") 370

392 Appendix C: Code Examples HAHTtalk Basic ' ' The command handler has already added a new record to ' the recordset, so we can get references to the Name ' and Picture fields in that record. Write the name ' me to the Name field. ' Set picturefld = danameandpict.getrecordset(). _ getfield("picture") Set namefld = danameandpict.getrecordset().getfield("name") namefld.setstring arequest.geturlfield("txtname") ' ' Open the image file, read chunks of data into a buffer, ' and copy the data to the record's Picture field. ' fread = FreeFile() Open spicturefilename for Binary Access Read As #fread flen = FileLen(sPictureFileName) nblksize = IIF(fLen < BLKSIZE, flen, BLKSIZE) sbuf = String$(nBlkSize, 0) While flen > 0 Get #fread,,sbuf picturefld.appendchunk sbuf flen = flen - nblksize If ( flen < nblksize ) AND ( flen > 0 ) Then nblksize = flen sbuf = String$(nBlkSize, 0) End If Wend ' ' Close the file. ' Close #fread onbind_exithandler: Exit Sub 371

393 Appendix C: Code Examples HAHTtalk Basic onbind_errorhandler: ' ' Dump any errors we want to here ' ahandlerinfo.setproceedaction _ DMConstants_PROCEED_DO_FAILURE_PAGE Resume onbind_exithandler 372

394 Appendix C: Code Examples Writing a custom authentication class This section presents the implementation of a Java class that authenticates users against information stored in an Access database. The table used for authentication contains two columns: UserName and Password. Java import com.haht.ado.abstract.*; import com.haht.access.*; public class CustomAuthentication implements Authentication { public boolean authorizeuser(string ausername, String apassword, String adomain) { Connection conn = new com.haht.ado.connection(); Recordset rs = new com.haht.ado.recordset(); // Open a connection to the database. try { conn.open("provider=hsodbc;dsn=authentication;" + "DBQ=C:\\Stan\\Authentication.mdb;" + "DriverId=25;FIL=MS Access;MaxBufferSize=512;" + "PageTimeout=5;"); } catch(java.lang.exception e) {} // Get the record containing the user name and password. rs.setactiveconnection(conn); String commandtext = "SELECT Password FROM Authentication" + " WHERE UserName = '" + ausername + "'"; try { rs.open(commandtext); } catch (java.lang.exception e) {} 373

395 Appendix C: Code Examples Java } } // Determine whether user should be authenticated. if (!(rs.getbof() == true && rs.geteof() == true)) { Field fld = rs.getfield("password"); if (fld.getstring().equals(apassword)) { rs.close(); conn.close(); return true; } rs.close(); conn.close(); return false; } rs.close(); conn.close(); return false; 374

396 ADO Primer D What s in this appendix Connections Opening a connection Executing a command against a connection Closing a connection Recordsets Creating a recordset Iterating through the records in a recordset Finding a specific record in a recordset Reading a record Updating a record Inserting a record Deleting a record Closing a recordset

397 Appendix D: ADO Primer What s in this appendix This appendix provides a very brief introduction to ADO programming by presenting short examples of how to perform common ADO operations in HAHTsite applications. For example, the appendix illustrates how to: open a connection create a recordset add a record to a recordset Each example is shown using both Java and HAHTtalk Basic syntax. A note for Java programmers: The Java ADO classes you use are not in the package com.ms.wfc.data (as they would be in a Microsoft ADO program), but are in the package com.haht.ado or com.haht.ado.abstract. You use the abstract classes in com.haht.ado.abstract when you declare a variable that will hold a reference to an ADO object. And you use the classes in com.haht.ado or in a package of user-defined ADO classes when you instantiate an ADO object. Generally, HAHTsite Java projects import com.haht.ado.abstract.* and fully qualify the names of classes in the package com.haht.ado or in a user-defined package. Connections An ADO Connection object represents a connection to a data source usually a relational database. For information on how to perform common operations using a Connection object, see the following sections: Opening a connection on page 376 Executing a command against a connection on page 378 Closing a connection on page 379 Opening a connection In a HAHTsite project, you can open a connection in one of two ways: by calling a Connection object s open method by calling a Java method or HAHTtalk Basic function that returns a Connection. Both ways of opening a connection are illustrated below. 376

398 Appendix D: ADO Primer Using an ADO method The code below shows how to open a connection by instantiating a Connection object and calling that object s open method. This open method is an overloaded method and may take zero or more of the following parameters: Parameter Data type Description A connection string String A data source name or a connection string containing a series of name/value pairs. A user name String The user name to be used for a database login. A password String The corresponding password. These examples use a connection string that specifies a provider and a data source. Java import com.haht.ado.abstract.*;... myconn = new com.haht.ado.connection(); myconn.open("provider=hsodbc;dsn=employees"); HAHTtalk Basic Dim myconn As new ADODB.Connection myconn.open "provider=hsodbc;dsn=employees" Note that the Java example creates a connection object of type com.haht.ado.connection and that the HAHTtalk Basic example creates one of type ADODB.Connection. Using a HAHTsite method or function HAHTsite includes a set of Java methods and HAHTtalk Basic functions that you can use to open, or get a reference to, a connection. For detailed information about these methods and functions, see Chapter 9, Programming with the Connection Manager. The Java methods are methods of the DMConnectionManager class: 377

399 Appendix D: ADO Primer getsharedconnectionbyid getsharedconnectionbyname openprivateconnectionbyid openprivateconnectionbyname There are four HAHTtalk Basic functions of the same names. The Java methods return objects of type com.haht.ado.connection, and the HAHTtalk Basic functions return objects of type ADODB.Connection. Calling a method or function that creates a private connection is comparable to calling a Connection object s open method. A new connection is created. The shared-connection methods and functions enable you to create a connection that can be used on a number of pages in an application. You can also share such a connection with HAHTsite data agents. The following examples get a reference to a shared connection by calling getsharedconnectionbyname. The one argument to this method/function is the name of an ADO connection that you ve created using the IDE. Java import com.haht.*; import com.haht.ado.abstract.*;... Connection myconn; try { myconn = Haht.getSession().getConnectionManager(). getsharedconnectionbyname("employeesconn"); } catch(hahtexception e) {} HAHTtalk Basic Dim myconn As ADODB.Connection Set myconn = getsharedconnectionbyname("employeesconn") Executing a command against a connection Once you ve opened a connection (or obtained a reference to an open connection), you can execute a command against that connection using the Connection object s execute or executeupdate (Java only) method. The first and sometimes only argument to this method is a string representing the 378

400 Appendix D: ADO Primer command to execute against the connection. This command can be a SQL statement, the name of a table, or the name of a stored procedure. In the example below, the command is a SQL statement that inserts a record into a database table. Java String insertcmd; int recordsaffected;... insertcmd = "INSERT INTO NAMES (FirstName, LastName) VALUES ('Jane', 'Doe')"; recordsaffected = myconn.executeupdate(insertcmd); HAHTtalk Basic Dim myrs As ADODB.Recordset Dim insertcmd As String... insertcmd = _ "INSERT INTO NAMES (FirstName, LastName) VALUES ('Jane', 'Doe')" Set myrs = myconn.execute(insertcmd) Closing a connection A connection is closed automatically when the object representing it goes out of scope; however, it s a good idea to close connections explicitly. You close a connection using the Connection object s close method. Java myconn.close(); myconn = null; HAHTtalk Basic myconn.close Set myconn = Nothing 379

401 Appendix D: ADO Primer Recordsets The ADO Recordset object is a container for a group of records returned as the result of a query. For information about common actions performed against recordsets, see the following sections: Creating a recordset on page 380 Iterating through the records in a recordset on page 381 Finding a specific record in a recordset on page 382 Reading a record on page 382 Updating a record on page 383 Inserting a record on page 383 Deleting a record on page 384 Closing a recordset on page 385 Creating a recordset You can create a recordset in a number of ways. For example, both the Connection and Command objects have execute methods that can return a recordset. The example below, however, creates a recordset containing data by instantiating a Recordset object and calling that object s open method. The first argument to this method specifies the source of the data; in this case, the data will be read from a database table called Names. This first argument can be a SQL statement, a table name, or the name of a stored procedure. The second argument is the name of a previously established Connection. Notice that the Java code returns an object of type com.haht.ado.recordset, while the HAHTtalk Basic code returns an object of type ADODB.Recordset. Java import com.haht.ado.abstract.*;... Recordset myrs = new com.haht.ado.recordset();... myrs.open("select * FROM Names", myconn); 380

402 Appendix D: ADO Primer HAHTtalk Basic Dim myrs As New ADODB.Recordset... myrs.open "SELECT * FROM Names", myconn Iterating through the records in a recordset Once you ve created a recordset, you ll need to be able to navigate it. One common requirement is to be able to look at each record in order. The following examples show you how to do this (assuming you opened your recordset using the default cursor type, forward-only). When you open the recordset (using the default cursor type), the current record is the first record in the recordset. The while statement checks to make sure that the current record pointer is not pointing beyond the last record in the recordset. As long as this condition is true, you want to process the record and then move to the next record. Java while (!myrs.geteof()) {... myrs.movenext(); } HAHTtalk Basic while (not myrs.eof)... myrs.movenext wend Note - If you opened your recordset using a cursor type other than the default that is, using a static cursor or a dynamic cursor you should call the recordset s movefirst method to move the current record pointer to the first record of the recordset before you begin iterating through the records. 381

403 Appendix D: ADO Primer Finding a specific record in a recordset In addition to iterating through the records in a recordset, you ll often want to find a particular record in a recordset. You can find a record that meets a specific criterion using the Recordset s find method. This method takes three arguments. The first is a string that specifies the criterion that must be met. This criterion has the form fieldname operator value. The second argument is a Boolean value indicating whether the find operation should skip the current record. The third argument is a constant that dictates the direction of the search: forward or backward. Java myrs.find("firstname = 'Jane'", 0, AdoEnums.SearchDirection.FORWARD); HAHTtalk Basic myrs.find "FirstName = 'Jane'", 0, adsearchforward Reading a record Each record in a recordset has associated with it a Fields collection, which contains the individual fields that make up the record. You read a record by making it the current record and then reading the individual fields in the record. You can access a field either by its name or by its position in the record. Java String firstname; String lastname;... firstname = myrs.getfield("firstname").getstring(); lastname = myrs.getfield("lastname").getstring(); 382

404 Appendix D: ADO Primer HAHTtalk Basic Dim firstname As String Dim lastname As String... firstname = myrs.fields(0) lastname = myrs.fields(1) Updating a record To update a record, you write data to one or more of the record s fields and then call the Recordset s update method. If you forget to update the record before you move the recordset s record pointer, your changes will be lost. Java myrs.open("select * FROM Names", myconn, AdoEnums.CursorType.KEYSET, AdoEnums.LockType.OPTIMISTIC);... myrs.getfield("lastname").setstring("smith"); myrs.update(); HAHTtalk Basic myrs.open "SELECT * FROM Names", myconn, adopenkeyset, _ adlockoptimistic... myrs.fields("lastname") = "Smith" myrs.update Inserting a record To insert a new record in a recordset, you perform the following steps: 1 Add a new record to the recordset by calling the Recordset s addnew method. 2 Write data to the new record. 3 Update the recordset. 383

405 Appendix D: ADO Primer Java myrs.open("select * FROM Names", myconn, AdoEnums.CursorType.KEYSET, AdoEnums.LockType.OPTIMISTIC); myrs.addnew(); myrs.getfield("firstname").setstring("john"); myrs.getfield("lastname").setstring("smith"); myrs.update(); HAHTtalk Basic myrs.open "SELECT * FROM Names", myconn, adopenkeyset, _ adlockoptimistic myrs.addnew myrs.fields("firstname") = "John" myrs.fields("lastname") = "Smith" myrs.update Deleting a record Deleting a record is simple. You just position the current record pointer appropriately and call the Recordset s delete method. Java myrs.open("select * FROM Names", myconn, AdoEnums.CursorType.KEYSET, AdoEnums.LockType.OPTIMISTIC); myrs.find("firstname = 'Jane'", 0, AdoEnums.SearchDirection.FORWARD); myrs.delete(); HAHTtalk Basic myrs.open "SELECT * FROM Names", myconn, adopenkeyset, _ adlockoptimistic myrs.find "FirstName = 'Jane'", 0, adsearchforward myrs.delete 384

406 Appendix D: ADO Primer Closing a recordset A recordset is closed if: you allow the variable being used to address it to go out of scope you call the Recordset s close method The examples below illustrate how to call the close method. Java myrs.close(); myrs = null; HAHTtalk Basic myrs.close Set myrs = Nothing 385

407 Appendix D: ADO Primer 386

408 ADO Extensions E What s in this appendix Extensions to the Java interface ADO tracing in Java projects Additional appendchunk methods The Variant data type Extensions to the HAHTtalk Basic interface ADO tracing in HAHTtalk Basic projects Functions for managing connections

409 Appendix E: ADO Extensions What s in this appendix HAHTsite s ADO interface matches the Microsoft interface almost exactly. However, a few extensions have been introduced to make debugging ADO code easier, to make sure that Java and HAHTtalk Basic projects have the same capabilities, and just to make programming easier. This appendix contains two mains sections: one on extensions to the Java interface and one on extensions to the Basic interface. See the appropriate subsection below: Extensions to the Java interface on page 388 Extensions to the HAHTtalk Basic interface on page 391 Extensions to the Java interface The main extensions to the Java interface are the addition of an ADO tracing facility, additional appendchunk methods, and the definition of a HAHTsite Variant class. For information on these extensions, see the sections listed below: ADO tracing in Java projects on page 388 Additional appendchunk methods on page 390 The Variant data type on page 390 ADO tracing in Java projects To help you debug your ADO code, HAHTsite adds an ADO-tracing feature. If you turn tracing on in your program, information about ADO operations is written to a log file. A sample trace file is shown below. 388

410 Appendix E: ADO Extensions ADO tracing in a Java project [17:15:07.848, 00173, 00162] settracing (1) [17:15:07.858, 00173, 00162] com.haht.ado.abstract.connection conn1 [17:15:07.858, 00173, 00162] conn1 = new com.haht.ado.connection () [17:15:07.858, 00173, 00162] conn1.setprovider ("HSODBC") [17:15:07.858, 00173, 00162] conn1.open ("Provider=HSODBC; DSN=Employees;DBQ=C:\Stan\Employees.mdb;DriverId=25;FIL=MS Access;MaxBufferSize=512;PageTimeout=5;") [17:15:08.369, 00173, 00162] rs2.open ("SELECT * FROM Names", conn1, CursorTypeEnum.adOpenKeyset, LockTypeEnum.adLock Optimistic) [17:15:08.399, 00173, 00162] rs2.find ("FirstName = 'Jane'", 0, SearchDirectionEnum.adSearchForward) [17:15:08.429, 00173, 00162] rs2.update () This trace file is written to the root directory of the drive on which the Application Server is installed (Windows NT) or /tmp (UNIX systems). The file is given a name of the form trace_ado_stateid.log. To turn ADO tracing on in a Java project Call the static method com.haht.ado.constants.settracing. The single argument to this method is a constant or the bitwise OR of two or more constants that indicates the type of tracing you are requesting. The constants you can use are listed in the table below. Note - The constants are static variables of the Constants class, so you should prepend com.haht.ado.constants. to each constant. Constant adgeneraltracing adtimingtracing Meaning logs many (but not all) of the ADO calls and their arguments. This type of tracing uses relatively little overhead and should not affect performance severely, unlike ODBC tracing. adds End trace entries so that you can see how long some ADO calls took to complete 389

411 Appendix E: ADO Extensions Constant adcoltimingtracing adgetvaltracing adsetvaltracing Meaning times calls to Field.finalize, Field.getString, and Field.isNull traces getdatatype operations for Field objects traces setdatatype operations for Field objects To turn ADO tracing off in a Java project Call settracing with an argument of 0. Additional appendchunk methods Four appendchunk methods have been added for writing binary or textual data to fields and parameters. Class Field Parameter Methods public void appendchunk(byte[] bytes, int nbytes) public void appendchunk(char[] chars, int nchars) public void appendchunk(byte[] bytes, int nbytes) public void appendchunk(char[] chars, int nchars) Often the last chunk of data you need to append to a field or parameter does not fill the byte or character array you re using as a buffer. These methods let you specify exactly how many bytes or characters you want to append with your final call to appendchunk. The Variant data type HAHTsite ADO methods that take a Variant as an argument, or return a Variant, use objects of the class com.haht.com.variant, instead of com.ms.com.variant. 390

412 Appendix E: ADO Extensions Extensions to the HAHTtalk Basic interface The principal extensions to the HAHTtalk Basic interface are the addition of an ADO-tracing feature and the inclusion of Basic functions/methods for working with private and shared connections. For further information on these subjects, see the sections listed below: ADO tracing in HAHTtalk Basic projects on page 391 Functions for managing connections on page 391 ADO tracing in HAHTtalk Basic projects The ADO-tracing feature discussed in ADO tracing in Java projects on page 388 is also available in HAHTtalk Basic projects. To turn tracing on, you call the function setadotracing, which requires one argument: a constant indicating the type of tracing you re requesting. The constants you can use are the same as the constants you use in Java projects. Note - The argument to setadotracing can also be the bitwise OR of two or more constants. Functions for managing connections In Java projects, you can use methods of the DMConnectionManager class to: open a private connection get a reference to a shared connection close a private connection These method return, or take as an argument, an object of type com.haht.ado.abstract.connection. In HAHTtalk Basic projects, you re usually working with objects of type ADODB.Connection. HAHTsite provides the following functions/methods to provide a comparable interface in HAHTtalk Basic projects. The four functions listed below return an object of type ADODB.Connection: getsharedconnectionbyid getsharedconnectionbyname getprivateconnectionbyid getprivateconnectionbyname In addition, the class ADODB.Connection defines a closeprivateconnection method that you can use to close private connections. 391

413 Appendix E: ADO Extensions For further information about private and shared connections, see Chapter 9, Programming with the Connection Manager. 392

414 Index A access control 270 enabling 272 access package (Java) 5 Active Server Pages 3 ActiveX Data Objects (ADO) 6 closing connections 379 closing recordsets 385 creating recordsets 380 deleting records 384 executing commands against connections 378 finding records in recordsets 382 HAHTsite extensions to 387 inserting records 383 navigating recordsets 381 opening connections 376 primer 375 reading records 382 updating records 383 addprivilege (Session class) 274 Application class 298 editing (Java projects) 25 application directories for HAHTtalk Basic projects 70 for Java projects 39 Application object 97 method summary 102 retrieving properties 100 variables 98 application root directory 71 approot 40, 71 array datatypes 72 attachments retrieving 122 authenticating users using a Web server 288 using the Login widget 277 using the Server Object Model 286 authentication class OSAuthentication 284 user-defined 285 Authentication interface 284, 285, 299 authorizeuser (Authentication interface) 286 B Breakpoint Manager 339 breakpoints 338 browser compatibility issues 249 built-in objects 90 getting references 91 Button class 165 button form fields 165 associating user code with 183 C CAB files 28 Call Stack window 344 Cascading Style Sheets 252 check box form fields 167 Checkbox class 167 class declaration (Java projects) 19 class files 28 Client Scripts view 238, 240, 248 client-side scripts See scripts closeprivateconnection (DMConnectionManager class) 232 code editor HAHTtalk Basic projects 67 Java projects 37 code examples calling a subroutine from a form 362 custom authentication class 373 modifying a command handler 370 code pages adding to a project 60 saving HAHTtalk Basic projects 61 COM objects using with HAHTtalk Basic 305 combo box form fields 168 Combo class 168 command handlers 189 changing the flow of control in 225 customizing 216 examples of customized handlers 217 structure of 212 common files (Java)

415 Index Common Object Request Broker Architecture (CORBA) 9, 310 building clients 315 building servers 318 in HAHTtalk Basic projects 329 Naming Service 329 compiler HAHTtalk Basic 69 finding compile-time errors 69 Java 38 debug option 39 finding compile-time errors 39 Connection class (ADO) 376 connections closing 379 executing commands against 378 opening 230, 376 constructor (Java projects) 19 cookies cookie collections 121, 128 multiple cookies with the same name 122 retrieving cookie values 121 setting 127 corba package (Java) 5 createfileurl (Session class) 111 createmapurl (Session class) 111 createpageurl (Session class) 111 createstaticurl (Session class) 113 custom Form Handler widgets 145 creating 152 writing the form-handler function 145 D data agents 188 enabling tracing 210 filtering records 205 getting a reference to a data agent s connection 198 getting a reference to a data agent s recordset 200 getting parameters to stored procedures 202 getting the values of data-agent fields 196 handling errors 210 limiting the maximum number of records 199 making a recordset read only 199 performing an action 192 refreshing data 203 setting a data agent s command 190 setting the values of data-agent fields 196 sorting records 204 data types C/C++and HAHTtalk Basic 304 datamanager package (Java) 4 datatypes arrays 72 scalars 72 debugger windows 340 Call Stack window 344 Output window, Debug tab 341 Threads window 345 Variable window 341 Watch window 343 debugging 10, 332 compiling with debug option 39 executing code 336 procedure stepping 338 requirements for 332 single stepping 337 starting a session 333 using breakpoints 338 directives, precompiler (HAHTtalk Basic projects) 64 directories static root 70 distributed-object applications 310 DLLs datatype mapping 304 DMConnectionManager class 230 document object models 237, 250 browsing 241 Dynamic HTML 252 dynamic pages calling from HAHTtalk Basic 65 calling from Java 30 E enabling access control 272 endheaders (Response class) 126 environment variables retrieving 122 error handler HAHTtalk Basic projects 60 event handling in Java projects 31 exception handler Java projects

416 Index exit handler HAHTtalk Basic projects 59 expressions HAHTtalk Basic 49 formatting 50 in dialog boxes 50 Java projects formatting 15 in dialog boxes 15 F File Upload class 168 File Upload form fields 140, 168 adding to a page 141 files submitting with forms 140 form method 117 form fields 163 buttons 165 check boxes 167 combo boxes 168 File Upload 140, 168 list boxes 169 radio buttons 175 setting properties of 156 text areas 178 text boxes 178 form handler HAHTtalk Basic projects 56 Java projects 23 Form Handler widgets custom 145 creating 152 writing the form-handler function 145 form handlers 212 form package (Java) 4 FormField class 163 forms calling subroutines from 134 submitting files with 140 G GateKeeper 329 GET and POST methods 117 getappdata (Application class) 100 getbof (Recordset class) 159 getcookie (Request class) 121 getdirname (Application class) 40, 71 geteof (Recordset class) 159 geterror (DataAgent class) 210 geterrorcount (DataAgent class) 210 getrecordset (DataAgent class) 200 getservervariable (Request class) 122 getservervariablecount (Request class) 122 getsharedconnectionbyname (DMConnectionManager class) 231 getstaticroot (Application class) 40, 70 getstaticurl (Session class) 40, 70 geturl (Session class) 109 geturlattachment (Request class) 144 geturlattachmentcount (Request class) 122 geturlattachmentexists (Request class) 122, 143 geturlattachmenttype (Request class) 122 geturlfield (Request class) 119 geturlfieldcount (Request class) 119 geturlfieldexists (Request class) 119 getuserroot (Application class) 40, 71 getvalue (FormField class) 182 getwriter (Response class) 129 Globals.hbs 63, 64 H HahtApplication.java 25 HahtSession.java 25 HAHTsite Server Object Model, See Server Object Model 89 HAHTtalk Basic 2 compared to Visual Basic 72 compiling 69 data types 72 editing code 67 error handling 73 file I/O 73 help for keywords 69 naming conventions 72 subroutines and functions 73 syntax checking 69 using COM objects 305 variable scope 72 HAHTtalk Basic projects adding code pages to a project 60 and server-side code view 52 calling dynamic pages 65 calling external logic 47 code editor

417 Index error handler 60 event handling 66 exit handler 59 generated code for a page 53 Globals.hbs 63 include files 53, 63 in-line code 48 naming conventions 62 page entry point 57 precompiler directives 64 server-side code 46 working with 46 headers adding content information 127 testing for "in headers" 127 writing 126 hssecurityprivileges database table 290 HTML writing 129 HTML Tags view 246 HtmlOut 260 HAHTtalk Basic example 262 HAHTtalk Basic include files 260 HAHTtalk Basic routines 261 Java class 264 Java example 265 HtmlWriter 129 I IDL compiler 311 IDL files 311 import statements (Java projects) 19 include files and HAHTtalk Basic projects 53 external includes (HAHTtalk Basic projects) 63 in HAHTtalk Basic projects 63 project includes (HAHTtalk Basic projects) 63 inheaders (Response class) 127 in-line code expressions Java projects 14 in HAHTtalk Basic projects 48 statements Java projects 15 insertelementat (Listbox class) 172 Internet Explorer 249 ismultiple (Listbox class) 172 isnewapp (Session class) 113 J JAR files 28 Java class files 28 code editor 37 compiling 38 file types 27 files adding to a project 26 JAR files 28 Java class directory 71 Java projects application directories 39 event handling 31 exception handler 23 form handler 23 in-line code 13 naming conventions 30 page, generated code for 18 server-side code 12 server-side code view 17 writing HTML output 23 javaroot 71 JavaScript 237, 238, 249 L layers (Netscape) 252 list box form fields 169 adding elements to a list 171 finding an item in a list 173 getting and setting properties 173 selecting an element in a list 172 list elements creating 169 getting and setting properties 171 Listbox class 169 ListElement class 169 logging in to an application 276 Login widget 277, 279 lookupprivileges (UserProfile interface) 292 M methods calling from dialog boxes Java projects 17 WebApp object

418 Index N naming conventions Java 30 Naming Service 329 Netscape Layers 252 Netscapte Navigator 249 O onend (Application class) 31 onend (Session class) 31 onsessionend (Application class) 31 example 33 onsessionstart (Application class) 31 example 33 onstart (Application class) 31 onstart (Session class) 31 openprivateconnectionbyname (DMConnectionManager class) 232 out.print statement 129 P package statement (Java projects) 19 Packages folder (Java projects) 26 page run method (Java projects) 20 page structure HAHTtalk Basic projects 53 Java projects 20 performaction (DataAgent class) 193 precompiler directives (HAHTtalk Basic projects) 64 print 129 printing Java projects 23 private connections 230 closing 232 opening 232 privilege repository 289 privilege-lookup class DBUserProfile 291 user-defined 292 privileges 270 adding to a project 272 assigning to a page 273 assigning to a session 273 granting to users who log in to an application 276 looking up in a database 290 looking up in a nondatabase repository 291 looking up using the Server Object Model 293 required 270 session 270 Privileges class 5, 298 project package (Java) 3 pseudo methods, for WebApp object 352 PUBLISH_OS 64 PUBLISH_SERVERGROUP 64 PUBLISH_SITENAME 64 PUBLISH_WEBSERVER 64 R radio button form fields 175 Radiobutton class 175 Recordset class (ADO) 380 recordsets closing 385 creating 380 deleting records 384 finding records in 382 getting references to 200 getting the values of fields in a record 196, 382 inserting records 383 limiting the maximum number of records 199 making read only 199 navigating 381 performing actions against 192 refreshing the data in 203 setting the values of fields in a record 196 sorting records 204 updating records 383 referred projects 93 Request object 117 attachments 122 environment variables 122 field values, retrieving 117 method summary 123 references to in HAHTtalk Basic projects 59 in Java projects 22 retrieving cookie values 121 required privileges 270 Response object 126 cookies 127 headers 126 method summary

419 Index references to in HAHTtalk Basic projects 59 in Java projects 22 writing HTML output 129 Retrieving 117 run method (Java projects) 20 arguments 20 S scalar datatypes 72 script functions 238, 244 scripts 8, 236 choosing a language 238 event handlers 238 in-line 238, 243 page-scope functions 238, 244 with server-side expressions 257 secure-static pages 270 security 270 Server Object Model 3, 89 Application object 97 built-in objects 90 Request object 117 Response object 126 Session object 107 server-side code view 52, 217 Java projects 17 server-side Java called from HAHTtalk Basic 76 case sensitvity 80 CreateJavaObject function 77, 78 CreateTypedJavaNull function 78 differences between HAHTtalk Basic and Java 79 GetJavaClass function 78 locating objects 80 mapping data types 83 mapping parameter types 81 runtime errors 84 Session class 297 editing (Java projects) 25 Session object 107 creating a static URL 113 creating a URL 109, 111 method summary 114 state 107 timeout 108 variables 107 session privileges 270 session state 107 session timeout 108 setauthenticationclassbyname (Application class) 285 setcommand (DataAgent class) 190 setcommandtype (DataAgent class) 191 setcontenttype (Response class) 127 setcookie (Response class) 127 setdisplaytext (StaticText class) 176 setinitialaction (DataAgent class) 195 setlabel (FormField class) 160 setmaxrecords (DataAgent class) 199 setmultiple (Listbox class) 172 setpictureurl (Button class) 166 setpostsort (DataAgent class) 204 setprefilter (DataAgent class) 208 setpresort (DataAgent class) 204 setreadonly (DataAgent class) 199 setstyle (Button class) 166 settracing (DataAgent class) 211 setuserprofileclassbyname (Application class) 292 setvalue (FormField class) 160, 182 setvisible (FormField class) 159 setwriter (Response class) 129 shared connections 230 opening or getting a reference to 231 SmartAgent 329 state 107 statements HAHTtalk Basic 49 static root directory 40, 70 static URL 70 StaticText class 176 stored procedures getting the values of output parameters 202 subroutines and dialog boxes 51 as form actions 134 T text area form fields 178 text box form fields 178 TextArea class 178 Textbox class 178 Threads window 345 timeout 108 tracing, enabling

420 Index U URL creating 109, 111 user code associating with a button 183 User Login Page template 278 UserProfile interface 292, 299 userroot 40, 71 V Variable window 341 variables 107 and multiple processes 99 Application object 98 global (HAHTtalk Basic projects) 64 locking 99 VBScript 237, 238, 249 VisiBroker for Java 310 GateKeeper 329 installing 329 interoperability with other ORBs 328 SmartAgent 329 W Watch window 343 watched variables adding 343 removing 344 WebApp object methods 350 pseudo methods 352 whoami (Session class) 114 whocalledme (Session class) 114 writebinary (Response class) 129 Z ZIP files

421 Index 400

HAHTsite IDE and IP Installation Guide

HAHTsite IDE and IP Installation Guide HAHTsite IDE and IP Installation Guide IDE and IP Installation Guide release 4.0 Notice Copyright 1999 HAHT Software, Inc. All Rights Reserved May 1999 MN01-C-00-400-00 No part of this publication may

More information

HAHTsite Application Server Installation Guide

HAHTsite Application Server Installation Guide HAHTsite Application Server Installation Guide Application Server Installation Guide release 4.0 Notice Copyright 1999 HAHT Software, Inc. All Rights Reserved July 1999 MN04-C-00-400-00 No part of this

More information

HAHTsite Application Server Administration Guide

HAHTsite Application Server Administration Guide HAHTsite Application Server Administration Guide Application Server Administration Guide release 4.0 Notice Copyright 1999 HAHT Software, Inc. All Rights Reserved March 1999 MN05-C-00-400-00 No part of

More information

TIBCO Administrator User s Guide. Software Release 5.7.1 March 2012

TIBCO Administrator User s Guide. Software Release 5.7.1 March 2012 TIBCO Administrator User s Guide Software Release 5.7.1 March 2012 Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR BUNDLED TIBCO SOFTWARE IS SOLELY

More information

LabVIEW Internet Toolkit User Guide

LabVIEW Internet Toolkit User Guide LabVIEW Internet Toolkit User Guide Version 6.0 Contents The LabVIEW Internet Toolkit provides you with the ability to incorporate Internet capabilities into VIs. You can use LabVIEW to work with XML documents,

More information

Web Pages. Static Web Pages SHTML

Web Pages. Static Web Pages SHTML 1 Web Pages Htm and Html pages are static Static Web Pages 2 Pages tagged with "shtml" reveal that "Server Side Includes" are being used on the server With SSI a page can contain tags that indicate that

More information

ServletExec TM 6.0 Installation Guide. for Microsoft Internet Information Server SunONE Web Server Sun Java System Web Server and Apache HTTP Server

ServletExec TM 6.0 Installation Guide. for Microsoft Internet Information Server SunONE Web Server Sun Java System Web Server and Apache HTTP Server ServletExec TM 6.0 Installation Guide for Microsoft Internet Information Server SunONE Web Server Sun Java System Web Server and Apache HTTP Server ServletExec TM NEW ATLANTA COMMUNICATIONS, LLC 6.0 Installation

More information

CA Process Automation

CA Process Automation CA Process Automation Glossary Service Pack 04.0.01 This Documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the Documentation ) is

More information

FileMaker Server 9. Custom Web Publishing with PHP

FileMaker Server 9. Custom Web Publishing with PHP FileMaker Server 9 Custom Web Publishing with PHP 2007 FileMaker, Inc. All Rights Reserved. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker is a trademark of FileMaker,

More information

Web Dashboard User Guide

Web Dashboard User Guide Web Dashboard User Guide Version 10.2 The software supplied with this document is the property of RadView Software and is furnished under a licensing agreement. Neither the software nor this document may

More information

Microsoft Visual Basic 6.0 Desktop: Controls

Microsoft Visual Basic 6.0 Desktop: Controls Microsoft Visual Basic 6.0 Desktop: Controls Audience: Visual Basic 6.0 developers Prerequisites: An understanding of the fundamentals of Visual Basic 6.0 development; knowledge of Windows interface design

More information

For Introduction to Java Programming, 5E By Y. Daniel Liang

For Introduction to Java Programming, 5E By Y. Daniel Liang Supplement H: NetBeans Tutorial For Introduction to Java Programming, 5E By Y. Daniel Liang This supplement covers the following topics: Getting Started with NetBeans Creating a Project Creating, Mounting,

More information

DOCUMENTATION FILE RESTORE

DOCUMENTATION FILE RESTORE DOCUMENTATION Copyright Notice The use and copying of this product is subject to a license agreement. Any other use is prohibited. No part of this publication may be reproduced, transmitted, transcribed,

More information

Professional. SlickEdif. John Hurst IC..T...L. i 1 8 О 7» \ WILEY \ Wiley Publishing, Inc.

Professional. SlickEdif. John Hurst IC..T...L. i 1 8 О 7» \ WILEY \ Wiley Publishing, Inc. Professional SlickEdif John Hurst IC..T...L i 1 8 О 7» \ WILEY \! 2 0 0 7 " > Wiley Publishing, Inc. Acknowledgments Introduction xiii xxv Part I: Getting Started with SiickEdit Chapter 1: Introducing

More information

NetBeans IDE Field Guide

NetBeans IDE Field Guide NetBeans IDE Field Guide Copyright 2005 Sun Microsystems, Inc. All rights reserved. Table of Contents Introduction to J2EE Development in NetBeans IDE...1 Configuring the IDE for J2EE Development...2 Getting

More information

TIBCO Runtime Agent Authentication API User s Guide. Software Release 5.8.0 November 2012

TIBCO Runtime Agent Authentication API User s Guide. Software Release 5.8.0 November 2012 TIBCO Runtime Agent Authentication API User s Guide Software Release 5.8.0 November 2012 Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR BUNDLED

More information

Building Applications Using Micro Focus COBOL

Building Applications Using Micro Focus COBOL Building Applications Using Micro Focus COBOL Abstract If you look through the Micro Focus COBOL documentation, you will see many different executable file types referenced: int, gnt, exe, dll and others.

More information

understand how image maps can enhance a design and make a site more interactive know how to create an image map easily with Dreamweaver

understand how image maps can enhance a design and make a site more interactive know how to create an image map easily with Dreamweaver LESSON 3: ADDING IMAGE MAPS, ANIMATION, AND FORMS CREATING AN IMAGE MAP OBJECTIVES By the end of this part of the lesson you will: understand how image maps can enhance a design and make a site more interactive

More information

WebLOAD IDE User's Guide Version 8.0

WebLOAD IDE User's Guide Version 8.0 WebLOAD IDE User's Guide Version 8.0 RadView Software The software supplied with this document is the property of RadView Software and is furnished under a licensing agreement. Neither the software nor

More information

http://alice.teaparty.wonderland.com:23054/dormouse/bio.htm

http://alice.teaparty.wonderland.com:23054/dormouse/bio.htm Client/Server paradigm As we know, the World Wide Web is accessed thru the use of a Web Browser, more technically known as a Web Client. 1 A Web Client makes requests of a Web Server 2, which is software

More information

SAS IT Resource Management 3.2

SAS IT Resource Management 3.2 SAS IT Resource Management 3.2 Reporting Guide Second Edition SAS Documentation The correct bibliographic citation for this manual is as follows: SAS Institute Inc 2011. SAS IT Resource Management 3.2:

More information

MOVING THE SENIOR DEVELOPMENT CLASS FROM WEB DEVELOPMENT TO LIFE CYCLE DEVELOPMENT A CASE FOR VISUAL STUDIO 2005

MOVING THE SENIOR DEVELOPMENT CLASS FROM WEB DEVELOPMENT TO LIFE CYCLE DEVELOPMENT A CASE FOR VISUAL STUDIO 2005 MOVING THE SENIOR DEVELOPMENT CLASS FROM WEB DEVELOPMENT TO LIFE CYCLE DEVELOPMENT A CASE FOR VISUAL STUDIO 2005 Thom Luce, Ohio University, [email protected] ABSTRACT Information Systems programs in Business

More information

TIBCO Runtime Agent Domain Utility User s Guide Software Release 5.8.0 November 2012

TIBCO Runtime Agent Domain Utility User s Guide Software Release 5.8.0 November 2012 TIBCO Runtime Agent Domain Utility User s Guide Software Release 5.8.0 November 2012 Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR BUNDLED TIBCO

More information

Java Application Developer Certificate Program Competencies

Java Application Developer Certificate Program Competencies Java Application Developer Certificate Program Competencies After completing the following units, you will be able to: Basic Programming Logic Explain the steps involved in the program development cycle

More information

Apache Server Implementation Guide

Apache Server Implementation Guide Apache Server Implementation Guide 340 March Road Suite 600 Kanata, Ontario, Canada K2K 2E4 Tel: +1-613-599-2441 Fax: +1-613-599-2442 International Voice: +1-613-599-2441 North America Toll Free: 1-800-307-7042

More information

Business Enterprise Server Help Desk Integration Guide. Version 3.5

Business Enterprise Server Help Desk Integration Guide. Version 3.5 Business Enterprise Server Help Desk Integration Guide Version 3.5 June 30, 2010 Copyright Copyright 2003 2010 Interlink Software Services, Ltd., as an unpublished work. All rights reserved. Interlink

More information

Application Development Guide: Building and Running Applications

Application Development Guide: Building and Running Applications IBM DB2 Universal Database Application Development Guide: Building and Running Applications Version 8 SC09-4825-00 IBM DB2 Universal Database Application Development Guide: Building and Running Applications

More information

Application Interface Services Server for Mobile Enterprise Applications Configuration Guide Tools Release 9.2

Application Interface Services Server for Mobile Enterprise Applications Configuration Guide Tools Release 9.2 [1]JD Edwards EnterpriseOne Application Interface Services Server for Mobile Enterprise Applications Configuration Guide Tools Release 9.2 E61545-01 October 2015 Describes the configuration of the Application

More information

Using Microsoft Windows Authentication for Microsoft SQL Server Connections in Data Archive

Using Microsoft Windows Authentication for Microsoft SQL Server Connections in Data Archive Using Microsoft Windows Authentication for Microsoft SQL Server Connections in Data Archive 2014 Informatica Corporation. No part of this document may be reproduced or transmitted in any form, by any means

More information

Interstage Application Server V7.0 Single Sign-on Operator's Guide

Interstage Application Server V7.0 Single Sign-on Operator's Guide Interstage Application Server V7.0 Single Sign-on Operator's Guide Single Sign-on Operator's Guide - Preface Trademarks Trademarks of other companies are used in this user guide only to identify particular

More information

www.novell.com/documentation Policy Guide Access Manager 3.1 SP5 January 2013

www.novell.com/documentation Policy Guide Access Manager 3.1 SP5 January 2013 www.novell.com/documentation Policy Guide Access Manager 3.1 SP5 January 2013 Legal Notices Novell, Inc., makes no representations or warranties with respect to the contents or use of this documentation,

More information

Application Servers - BEA WebLogic. Installing the Application Server

Application Servers - BEA WebLogic. Installing the Application Server Proven Practice Application Servers - BEA WebLogic. Installing the Application Server Product(s): IBM Cognos 8.4, BEA WebLogic Server Area of Interest: Infrastructure DOC ID: AS01 Version 8.4.0.0 Application

More information

Guide to SAS/AF Applications Development

Guide to SAS/AF Applications Development Guide to SAS/AF Applications Development SAS Documentation The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2012. Guide to SAS/AF Applications Development. Cary, NC:

More information

Grid Computing in SAS 9.4 Third Edition

Grid Computing in SAS 9.4 Third Edition Grid Computing in SAS 9.4 Third Edition SAS Documentation The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2014. Grid Computing in SAS 9.4, Third Edition. Cary, NC:

More information

Web Server Configuration Guide

Web Server Configuration Guide Web Server Configuration Guide FOR WINDOWS & UNIX & LINUX DOCUMENT ID: ADC50000-01-0680-01 LAST REVISED: February 11, 2014 Copyright 2000-2014 by Appeon Corporation. All rights reserved. This publication

More information

Hyperion Performance Suite

Hyperion Performance Suite Hyperion Performance Suite Release 8.2 What s New Hyperion Solutions Corporation P/N: D832582000 Copyright 1999 2004 Hyperion Solutions Corporation. All rights reserved. Hyperion and Hyperion's product

More information

Scheduler Job Scheduling Console

Scheduler Job Scheduling Console Tivoli IBM Tivoli Workload Scheduler Job Scheduling Console Feature Level 1.3 (Revised December 2004) User s Guide SC32-1257-02 Tivoli IBM Tivoli Workload Scheduler Job Scheduling Console Feature Level

More information

SQLBase. Starter Guide 20-2905-1004

SQLBase. Starter Guide 20-2905-1004 SQLBase Starter Guide 20-2905-1004 Trademarks Centura, Centura net.db, Centura Ranger, the Centura logo, Centura Web Developer, Gupta, the Gupta logo, Gupta Powered, the Gupta Powered logo, Fast Facts,

More information

Novell ZENworks 10 Configuration Management SP3

Novell ZENworks 10 Configuration Management SP3 AUTHORIZED DOCUMENTATION Software Distribution Reference Novell ZENworks 10 Configuration Management SP3 10.3 November 17, 2011 www.novell.com Legal Notices Novell, Inc., makes no representations or warranties

More information

IBM Unica emessage Version 8 Release 6 February 13, 2015. User's Guide

IBM Unica emessage Version 8 Release 6 February 13, 2015. User's Guide IBM Unica emessage Version 8 Release 6 February 13, 2015 User's Guide Note Before using this information and the product it supports, read the information in Notices on page 403. This edition applies to

More information

Tutorial: BlackBerry Object API Application Development. Sybase Unwired Platform 2.2 SP04

Tutorial: BlackBerry Object API Application Development. Sybase Unwired Platform 2.2 SP04 Tutorial: BlackBerry Object API Application Development Sybase Unwired Platform 2.2 SP04 DOCUMENT ID: DC01214-01-0224-01 LAST REVISED: May 2013 Copyright 2013 by Sybase, Inc. All rights reserved. This

More information

Elgg 1.8 Social Networking

Elgg 1.8 Social Networking Elgg 1.8 Social Networking Create, customize, and deploy your very networking site with Elgg own social Cash Costello PACKT PUBLISHING open source* community experience distilled - BIRMINGHAM MUMBAI Preface

More information

Expanded contents. Section 1. Chapter 2. The essence off ASP.NET web programming. An introduction to ASP.NET web programming

Expanded contents. Section 1. Chapter 2. The essence off ASP.NET web programming. An introduction to ASP.NET web programming TRAINING & REFERENCE murach's web programming with C# 2010 Anne Boehm Joel Murach Va. Mike Murach & Associates, Inc. I J) 1-800-221-5528 (559) 440-9071 Fax: (559) 44(M)963 [email protected] www.murach.com

More information

Administration Quick Start

Administration Quick Start www.novell.com/documentation Administration Quick Start ZENworks 11 Support Pack 3 February 2014 Legal Notices Novell, Inc., makes no representations or warranties with respect to the contents or use of

More information

Visual COBOL ASP.NET Shopping Cart Demonstration

Visual COBOL ASP.NET Shopping Cart Demonstration Visual COBOL ASP.NET Shopping Cart Demonstration Overview: The original application that was used as the model for this demonstration was the ASP.NET Commerce Starter Kit (CSVS) demo from Microsoft. The

More information

WebMarshal User Guide

WebMarshal User Guide WebMarshal User Guide Legal Notice Copyright 2014 Trustwave Holdings, Inc. All rights reserved. This document is protected by copyright and any distribution, reproduction, copying, or decompilation is

More information

SDK Code Examples Version 2.4.2

SDK Code Examples Version 2.4.2 Version 2.4.2 This edition of SDK Code Examples refers to version 2.4.2 of. This document created or updated on February 27, 2014. Please send your comments and suggestions to: Black Duck Software, Incorporated

More information

Taleo Enterprise. Taleo Reporting Getting Started with Business Objects XI3.1 - User Guide

Taleo Enterprise. Taleo Reporting Getting Started with Business Objects XI3.1 - User Guide Taleo Enterprise Taleo Reporting XI3.1 - User Guide Feature Pack 12A January 27, 2012 Confidential Information and Notices Confidential Information The recipient of this document (hereafter referred to

More information

026-1010 Rev 7 06-OCT-2011. Site Manager Installation Guide

026-1010 Rev 7 06-OCT-2011. Site Manager Installation Guide 026-1010 Rev 7 06-OCT-2011 Site Manager Installation Guide Retail Solutions 3240 Town Point Drive NW, Suite 100 Kennesaw, GA 30144, USA Phone: 770-425-2724 Fax: 770-425-9319 Table of Contents 1 SERVER

More information

WebEx Meeting Center User s Guide

WebEx Meeting Center User s Guide WebEx Meeting Center User s Guide Version 8 Copyright WebEx Communications, Inc. reserves the right to make changes in the information contained in this publication without prior notice. The reader should

More information

How To Install Caarcserve Backup Patch Manager 27.3.2.2 (Carcserver) On A Pc Or Mac Or Mac (Or Mac)

How To Install Caarcserve Backup Patch Manager 27.3.2.2 (Carcserver) On A Pc Or Mac Or Mac (Or Mac) CA ARCserve Backup Patch Manager for Windows User Guide r16 This Documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the Documentation

More information

core. Volume I - Fundamentals Seventh Edition Sun Microsystems Press A Prentice Hall Title ULB Darmstadt

core. Volume I - Fundamentals Seventh Edition Sun Microsystems Press A Prentice Hall Title ULB Darmstadt core. 2008 AGI-Information Management Consultants May be used for personal purporses only or by libraries associated to dandelon.com network. Volume I - Fundamentals Seventh Edition CAY S. HORSTMANN GARY

More information

IBM VisualAge for Java,Version3.5. Remote Access to Tool API

IBM VisualAge for Java,Version3.5. Remote Access to Tool API IBM VisualAge for Java,Version3.5 Remote Access to Tool API Note! Before using this information and the product it supports, be sure to read the general information under Notices. Edition notice This edition

More information

http://msdn.microsoft.com/en-us/library/4w3ex9c2.aspx

http://msdn.microsoft.com/en-us/library/4w3ex9c2.aspx ASP.NET Overview.NET Framework 4 ASP.NET is a unified Web development model that includes the services necessary for you to build enterprise-class Web applications with a minimum of coding. ASP.NET is

More information

Release 6.2.1 System Administrator s Guide

Release 6.2.1 System Administrator s Guide IBM Maximo Release 6.2.1 System Administrator s Guide Note Before using this information and the product it supports, read the information in Notices on page Notices-1. First Edition (January 2007) This

More information

J j enterpririse. Oracle Application Express 3. Develop Native Oracle database-centric web applications quickly and easily with Oracle APEX

J j enterpririse. Oracle Application Express 3. Develop Native Oracle database-centric web applications quickly and easily with Oracle APEX Oracle Application Express 3 The Essentials and More Develop Native Oracle database-centric web applications quickly and easily with Oracle APEX Arie Geller Matthew Lyon J j enterpririse PUBLISHING BIRMINGHAM

More information

Oracle Enterprise Manager

Oracle Enterprise Manager Oracle Enterprise Manager Getting Started with Oracle Change Management Pack Release 9.2.0 March 2002 Part No. A96679-01 Oracle Enterprise Manager Getting Started with Oracle Change Management Pack, Release

More information

http://docs.trendmicro.com

http://docs.trendmicro.com Trend Micro Incorporated reserves the right to make changes to this document and to the products described herein without notice. Before installing and using the product, please review the readme files,

More information

CA Performance Center

CA Performance Center CA Performance Center Single Sign-On User Guide 2.4 This Documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the Documentation ) is

More information

Expedite for Windows Software Development Kit Programming Guide

Expedite for Windows Software Development Kit Programming Guide GXS EDI Services Expedite for Windows Software Development Kit Programming Guide Version 6 Release 2 GC34-3285-02 Fifth Edition (November 2005) This edition replaces the Version 6.1 edition. Copyright

More information

Unisys INFOIMAGE FOLDER ON WINDOWS NT. Connector for Microsoft Exchange. Getting Started Guide

Unisys INFOIMAGE FOLDER ON WINDOWS NT. Connector for Microsoft Exchange. Getting Started Guide INFOIMAGE FOLDER ON WINDOWS NT Connector for Microsoft Exchange Unisys Getting Started Guide Copyright 1999 Unisys Corporation. All rights reserved. Unisys is a registered trademark of Unisys Corporation.

More information

CalREDIE Browser Requirements

CalREDIE Browser Requirements CalREDIE Browser Requirements Table of Contents Section 1: Browser Settings... 2 Section 2: Windows Requirements... 11 Section 3: Troubleshooting... 12 1 Section 1: Browser Settings The following browser

More information

ERIE COMMUNITY COLLEGE COURSE OUTLINE A. COURSE TITLE: CS 103 - WEB DEVELOPMENT AND PROGRAMMING FUNDAMENTALS

ERIE COMMUNITY COLLEGE COURSE OUTLINE A. COURSE TITLE: CS 103 - WEB DEVELOPMENT AND PROGRAMMING FUNDAMENTALS ERIE COMMUNITY COLLEGE COURSE OUTLINE A. COURSE TITLE: CS 103 - WEB DEVELOPMENT AND PROGRAMMING FUNDAMENTALS B. CURRICULUM: Mathematics / Computer Science Unit Offering C. CATALOG DESCRIPTION: (N,C,S)

More information

Microsoft SQL Server 2005 Reporting Services Step by Step

Microsoft SQL Server 2005 Reporting Services Step by Step Microsoft SQL Server 2005 Reporting Services Step by Step Stacia Misner; Hitachi Consulting To learn more about this book, visit Microsoft Learning at http://www.microsoft.com/mspress/books/9153.aspx 9780735622500

More information

Users Guide. Ribo 3.0

Users Guide. Ribo 3.0 Users Guide Ribo 3.0 DOCUMENT ID: DC37542-01-0300-02 LAST REVISED: April 2012 Copyright 2012 by Sybase, Inc. All rights reserved. This publication pertains to Sybase software and to any subsequent release

More information

TIBCO Hawk SNMP Adapter Installation

TIBCO Hawk SNMP Adapter Installation TIBCO Hawk SNMP Adapter Installation Software Release 4.9.0 November 2012 Two-Second Advantage Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR

More information

TIBCO ActiveMatrix BusinessWorks Plug-in for Microsoft SharePoint User s Guide

TIBCO ActiveMatrix BusinessWorks Plug-in for Microsoft SharePoint User s Guide TIBCO ActiveMatrix BusinessWorks Plug-in for Microsoft SharePoint User s Guide Software Release 1.0 Feburary 2013 Two-Second Advantage Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER

More information

Crystal Reports Installation Guide

Crystal Reports Installation Guide Crystal Reports Installation Guide Version XI Infor Global Solutions, Inc. Copyright 2006 Infor IP Holdings C.V. and/or its affiliates or licensors. All rights reserved. The Infor word and design marks

More information

SOA Software API Gateway Appliance 7.1.x Administration Guide

SOA Software API Gateway Appliance 7.1.x Administration Guide SOA Software API Gateway Appliance 7.1.x Administration Guide Trademarks SOA Software and the SOA Software logo are either trademarks or registered trademarks of SOA Software, Inc. Other product names,

More information

NetIQ Identity Manager Setup Guide

NetIQ Identity Manager Setup Guide NetIQ Identity Manager Setup Guide July 2015 www.netiq.com/documentation Legal Notice THIS DOCUMENT AND THE SOFTWARE DESCRIBED IN THIS DOCUMENT ARE FURNISHED UNDER AND ARE SUBJECT TO THE TERMS OF A LICENSE

More information

OVERVIEW OF ASP. What is ASP. Why ASP

OVERVIEW OF ASP. What is ASP. Why ASP OVERVIEW OF ASP What is ASP Active Server Pages (ASP), Microsoft respond to the Internet/E-Commerce fever, was designed specifically to simplify the process of developing dynamic Web applications. Built

More information

ASP.NET: THE NEW PARADIGM FOR WEB APPLICATION DEVELOPMENT

ASP.NET: THE NEW PARADIGM FOR WEB APPLICATION DEVELOPMENT ASP.NET: THE NEW PARADIGM FOR WEB APPLICATION DEVELOPMENT Dr. Mike Morrison, University of Wisconsin-Eau Claire, [email protected] Dr. Joline Morrison, University of Wisconsin-Eau Claire, [email protected]

More information

Windows PowerShell Cookbook

Windows PowerShell Cookbook Windows PowerShell Cookbook Lee Holmes O'REILLY' Beijing Cambridge Farnham Koln Paris Sebastopol Taipei Tokyo Table of Contents Foreword Preface xvii xxi Part I. Tour A Guided Tour of Windows PowerShell

More information

Citrix EdgeSight User s Guide. Citrix EdgeSight for Endpoints 5.4 Citrix EdgeSight for XenApp 5.4

Citrix EdgeSight User s Guide. Citrix EdgeSight for Endpoints 5.4 Citrix EdgeSight for XenApp 5.4 Citrix EdgeSight User s Guide Citrix EdgeSight for Endpoints 5.4 Citrix EdgeSight for XenApp 5.4 Copyright and Trademark Notice Use of the product documented in this guide is subject to your prior acceptance

More information

TIBCO BusinessConnect Trading Partner Administration. Software Release 6.0 November 2011

TIBCO BusinessConnect Trading Partner Administration. Software Release 6.0 November 2011 TIBCO BusinessConnect Trading Partner Administration Software Release 6.0 November 2011 Important Information SOME TIBCO SOFTWARE EMBEDS OR BUNDLES OTHER TIBCO SOFTWARE. USE OF SUCH EMBEDDED OR BUNDLED

More information

SQL Server 2005 Reporting Services (SSRS)

SQL Server 2005 Reporting Services (SSRS) SQL Server 2005 Reporting Services (SSRS) Author: Alex Payne and Brian Welcker Published: May 2005 Summary: SQL Server 2005 Reporting Services is a key component of SQL Server 2005. Reporting Services

More information

Advantages of PML as an iseries Web Development Language

Advantages of PML as an iseries Web Development Language Advantages of PML as an iseries Web Development Language What is PML PML is a highly productive language created specifically to help iseries RPG programmers make the transition to web programming and

More information

CA APM Cloud Monitor. Scripting Guide. Release 8.2

CA APM Cloud Monitor. Scripting Guide. Release 8.2 CA APM Cloud Monitor Scripting Guide Release 8.2 This Documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the Documentation ) is for

More information

SAS 9.4 Intelligence Platform

SAS 9.4 Intelligence Platform SAS 9.4 Intelligence Platform Application Server Administration Guide SAS Documentation The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2013. SAS 9.4 Intelligence Platform:

More information

Administrator Operations Guide

Administrator Operations Guide Administrator Operations Guide 1 What You Can Do with Remote Communication Gate S 2 Login and Logout 3 Settings 4 Printer Management 5 Log Management 6 Firmware Management 7 Installation Support 8 Maintenance

More information

EMC Documentum Content Services for SAP iviews for Related Content

EMC Documentum Content Services for SAP iviews for Related Content EMC Documentum Content Services for SAP iviews for Related Content Version 6.0 Administration Guide P/N 300 005 446 Rev A01 EMC Corporation Corporate Headquarters: Hopkinton, MA 01748 9103 1 508 435 1000

More information

BarTender Integration Methods. Integrating BarTender s Printing and Design Functionality with Your Custom Application WHITE PAPER

BarTender Integration Methods. Integrating BarTender s Printing and Design Functionality with Your Custom Application WHITE PAPER BarTender Integration Methods Integrating BarTender s Printing and Design Functionality with Your Custom Application WHITE PAPER Contents Introduction 3 Integrating with External Data 4 Importing Data

More information

CA Identity Manager. Glossary. r12.5 SP8

CA Identity Manager. Glossary. r12.5 SP8 CA Identity Manager Glossary r12.5 SP8 This documentation, which includes embedded help systems and electronically distributed materials, (hereinafter referred to as the Documentation ) is for your informational

More information

Network Monitoring Tool with LAMP Architecture

Network Monitoring Tool with LAMP Architecture Network Monitoring Tool with LAMP Architecture Shuchi Sharma KIIT College of Engineering Gurgaon, India Dr. Rajesh Kumar Tyagi JIMS, Vasant Kunj New Delhi, India Abstract Network Monitoring Tool enables

More information

Building Java Servlets with Oracle JDeveloper

Building Java Servlets with Oracle JDeveloper Building Java Servlets with Oracle JDeveloper Chris Schalk Oracle Corporation Introduction Developers today face a formidable task. They need to create large, distributed business applications. The actual

More information

Heterogeneous Replication Guide. Replication Server 15.5

Heterogeneous Replication Guide. Replication Server 15.5 Heterogeneous Replication Guide Replication Server 15.5 DOCUMENT ID: DC36924-01-1550-01 LAST REVISED: March 2010 Copyright 2010 by Sybase, Inc. All rights reserved. This publication pertains to Sybase

More information

ARIS Design Platform Getting Started with BPM

ARIS Design Platform Getting Started with BPM Rob Davis and Eric Brabander ARIS Design Platform Getting Started with BPM 4y Springer Contents Acknowledgements Foreword xvii xix Chapter 1 An Introduction to BPM 1 1.1 Brief History of Business Process

More information

User Guide. Version 3.2. Copyright 2002-2009 Snow Software AB. All rights reserved.

User Guide. Version 3.2. Copyright 2002-2009 Snow Software AB. All rights reserved. Version 3.2 User Guide Copyright 2002-2009 Snow Software AB. All rights reserved. This manual and computer program is protected by copyright law and international treaties. Unauthorized reproduction or

More information

Citrix Access Gateway Enterprise Edition Citrix Access Gateway Plugin for Java User Guide. Citrix Access Gateway 8.1, Enterprise Edition

Citrix Access Gateway Enterprise Edition Citrix Access Gateway Plugin for Java User Guide. Citrix Access Gateway 8.1, Enterprise Edition Citrix Access Gateway Enterprise Edition Citrix Access Gateway Plugin for Java User Guide Citrix Access Gateway 8.1, Enterprise Edition Copyright and Trademark Notice Use of the product documented in this

More information

CA Nimsoft Service Desk

CA Nimsoft Service Desk CA Nimsoft Service Desk Configure Outbound Web Services 7.13.7 Legal Notices Copyright 2013, CA. All rights reserved. Warranty The material contained in this document is provided "as is," and is subject

More information

HP Storage Essentials Storage Resource Management Report Optimizer Software 6.0. Building Reports Using the Web Intelligence Java Report Panel

HP Storage Essentials Storage Resource Management Report Optimizer Software 6.0. Building Reports Using the Web Intelligence Java Report Panel HP Storage Essentials Storage Resource Management Report Optimizer Software 6.0 Building Reports Using the Web Intelligence Java Report Panel First edition: July 2008 Legal and notice information Copyright

More information

HOW TO SILENTLY INSTALL CLOUD LINK REMOTELY WITHOUT SUPERVISION

HOW TO SILENTLY INSTALL CLOUD LINK REMOTELY WITHOUT SUPERVISION HOW TO SILENTLY INSTALL CLOUD LINK REMOTELY WITHOUT SUPERVISION Version 1.1 / Last updated November 2012 INTRODUCTION The Cloud Link for Windows client software is packaged as an MSI (Microsoft Installer)

More information

Oracle Fusion Middleware

Oracle Fusion Middleware Oracle Fusion Middleware Administrator s Guide for Oracle Directory Integration Platform 11g Release 1 (11.1.1) E10031-03 April 2010 Oracle Fusion Middleware Administrator's Guide for Oracle Directory

More information

Content Management Implementation Guide 5.3 SP1

Content Management Implementation Guide 5.3 SP1 SDL Tridion R5 Content Management Implementation Guide 5.3 SP1 Read this document to implement and learn about the following Content Manager features: Publications Blueprint Publication structure Users

More information

Business Application Services Testing

Business Application Services Testing Business Application Services Testing Curriculum Structure Course name Duration(days) Express 2 Testing Concept and methodologies 3 Introduction to Performance Testing 3 Web Testing 2 QTP 5 SQL 5 Load

More information

Scheduling in SAS 9.4 Second Edition

Scheduling in SAS 9.4 Second Edition Scheduling in SAS 9.4 Second Edition SAS Documentation The correct bibliographic citation for this manual is as follows: SAS Institute Inc. 2015. Scheduling in SAS 9.4, Second Edition. Cary, NC: SAS Institute

More information

http://docs.trendmicro.com

http://docs.trendmicro.com Trend Micro Incorporated reserves the right to make changes to this document and to the products described herein without notice. Before installing and using the product, please review the readme files,

More information

ibaan ERP 5.2a Configuration Guide for ibaan ERP Windows Client

ibaan ERP 5.2a Configuration Guide for ibaan ERP Windows Client ibaan ERP 5.2a Configuration Guide for ibaan ERP Windows Client A publication of: Baan Development B.V. P.O.Box 143 3770 AC Barneveld The Netherlands Printed in the Netherlands Baan Development B.V. 2002.

More information

Release/Installation Notes

Release/Installation Notes AonixADT for Eclipse Release/Installation Notes Version 3.2.2, Build 136 UD/REL/ADTN0000-06053/001 Nov07 Aonix North America 5930 Cornerstone Court West, Suite 250 San Diego, CA 92121 Tel: (858) 457-2700

More information