In this article we are going to talk about Web development in general and it's typical problems. Then we will define the concept of component based Web development, how it can help developing complex Web applications. The main topic of this article is XVCL - an open source library that provides support for component-based development of Web apps. We will use sample applications shipped with XVCL to illustrate different topics starting from creating a simplest "Hello, World!" application and finishing with advanced topics of generating database driven HTML pages and creating custom components.contents
With classic CGI approach web application is invoked by a web server which passes it request parameters and the web application generates response content using simple string manipulation techniques, like string constants and literals, concatenation, Format function, etc.
The problem with classic CGI approach is its complexity. Because all HTML content lives inside of source files of programming languages like C++, Perl, etc. You cannot use any available HTML editors that provide such useful features like syntax highlighting, integrated help on HTML, etc.
As a solution to the problems of classic CGI approach, a set of new technologies was developed by different companies for different programming languages.
All these technologies can be combined under a common name of Template/Tag based Web technologies because all of them use some sort of HTML template that contains special markers or tags, which have a special meaning for the supporting framework. The framework parses those tags and invokes associated code to generate HTML content that will replace the tags. In case of ASP, JSP and PHP, this code is embedded into the HTML template itself. In case of ATL Server and Page Producer, the code resides in a separate source file.
Compared to classic CGI approach, Template/Tag based technologies provide a great improvement. You can use HTML editors and other available tools to significantly reduce the time required to build Web applications. These technologies are very useful if you are building a web site. Typically when building a web site, you have a lot of content and a relatively small amount of code for things like menus, animated buttons and other bells and whistles.
But essentially Template/Tag technologies are similar to the classic CGI in terms of the way they generate content. It all comes to use of strings and string manipulation functions.
Because HTML content is created by manipulating strings, nothing prevents you from using incorrect tag names, forgetting to close a tag or break containership relations between elements. This problem is not obvious when you are writing a new code, but it becomes very serious when you need to debug old code or add new features to the existing code.
Typically in Template/Tag based technologies code is reused by inclusion. You can define functions in a separate file and then use some sort of "include" directive to use it in your code. In Delphi, when you are using page producers, you create chains of page producers linked together so that one producer generates content used by another as a template and so forth.
When you reuse code based on Page Producer in Delphi programs, you need to make one producer generate special tags for the producer that you want to reuse. In other words, where in Windows program you would call a method of an object, in Web program you create a string that will cause that method to be executed. That string is not checked by compiler for errors and type compatibility, so you have to check it by hand.
Template/Tag approach is radically different from traditional Delphi component programming model. In VCL all visual objects are represented with objects that can be aggregated to build highly customizable, complex user interfaces. Because Template/Tag approach doesn't use component model it is very difficult if not impossible to build a design time support comparable to Form/Data Module designer in Delphi. The best you can do with template/tag approach is what we have now in Delphi - one-way tool with preview, something completely different from form designer, specialized for use only with MIDAS.
Think of how many third-party visual component libraries were created for Delphi. And how many components were created as extensions (not as replacements) for Page Producer/Internet Express architecture? I can't think of any big library that extends Page Producer/Internet Express. And the reason why, I think, is because Page Producer/Internet Express architecture was designed in a completely different from VCL way that doesn't allow generic high quality design time support and doesn't allow easy creation of different components.
XVCL attempts to address these issues and provide Delphi programmers with robust object oriented support for building highly dynamic web applications.contents
XVCL is a component library for Borland Delphi. It is an open source project, available free for commercial, corporate, educational and personal use and comes with complete source code. You can download the most recent copy of the library from http://xvcl.sourceforge.net. XVCL is a part of JEDI VCL; you can also find a link to our site from Project JEDI web site at http://www.delphi-jedi.org
The library is distributed under Mozilla public license (MPL). You can find more details about licensing at XVCL web site. The main restriction that MPL puts on users of the covered code is that if you use it in your work and make modifications to the source code you need to make these modifications available to the authors and other users of the code. In other words, the license doesn't allow you to take source code, change it and sell it as your own product without giving your changes back to the open source community.
One of the main goals of the project is to simplify development of HTML/XML application. The latest version of the library is 0.3; obviously there is a long way to go toward version 1.0. But even in its current state the library is already useful and can be used for Web development. We are using XVCL in development of CDWeb module of our Carpe Diem Electronic Timesheet product at Sage U.S. Holdings.
This is a classic "Hello, World" program - the simplest Delphi program that produces an HTML page containing "Hello, World" using XVCL.
The source code is located in Demos\HTML\HelloWorld directory of your XVCL installation.contents
As you can see from "Hello, World!" example, you create HTML content by manipulating objects. This is the main difference between XVCL and Template/Tag based technologies. All documents and HTML documents in particular are represented with objects of different classes. Hierarchy of classes and objects representing a document at run-time constitute Document Object Model.
Document Object Model in XVCL is designed based on XML DOM created by World Wide Web Consortium, but it is not an implementation of XML DOM. Since the purpose of DOM in XVCL is quite different, we didn't try to achieve compatibility with XML DOM. The purpose of XML DOM is to provide a standard interface for working with XML documents in general, XVCL attempts to provide type safety and ease of use for building XML documents.
TJvxNode is a base class of two other core classes - TJvxAttribute and TJvxElement.
For example, Value attribute of HTML <INPUT> element is represented by a descendant of TJvxAttribute class.
For example, HTML <TITLE> element is represented by a descendant of TJvxElement class.
For example TJvxXMLGenerator is a descendant of TJvxVisitor that used to generate XML/HTML content from document objects.
The nature of HTML documents is hierarchical. <HTML> element has <HEAD> and <BODY> child elements, <HEAD> has <TITLE> and so forth. XVCL objects are arranged in hierarchies using Parent, Attributes and Elements properties defined in TJvxNode class and inherited by all classes. To make one element a child element of another, you can either assign child's Parent property, or add child to Elements collection of the parent.
In the following example a <DIV> element is inserted into <BODY>
DivElement := TJvxHTMLDiv.Create(Self); DivElement.Text.Add('Hello World!'); DivElement.Parent := FHTML.Body;
This example illustrates use of document object hierarchies to create a simple user interface document - HTML form containing several different HTML controls.
The source code is located in Demos\HTML\Form directory of your XVCL installation.contents
One of the very common tasks in any software development is database application development. A database application displays and allows manipulating data retrieved from a database. Facilitating database development was one of the goals for XVCL design. A set of XVCL components allows building complex HTML documents that retrieve their content from database tables and other external sources.
This class is a base class of different data field components. Data fields in XVCL allow retrieving values of individual elements and attributes from elsewhere. Any document node that can have a value can be connected to a data field through TJvxNode.DataField property. When connected to a data field, document node loads data from the field automatically, every time the field is changed. The concept of data field in XVCL is very similar to the concept of data field (TField) in VCL.
For example, TJvxDBDataField allows you to make an HTML attribute retrieve it's value from a database table field.
This class represents an abstract data source. It provides access to a tabular data through a "cursor" - set of data fields, where each field points to the current record's field at any given point in time. The concept of data source is very similar to the concept of dataset (TDataSet) in VCL.
For example, TJvxDBDataSource allows you to connect to any TDataSet descendant.
When a data source is connected to a composite element using TJvxCompositeElement.DataSource property, from the outside, it appears that the element now has many child elements that are virtually stored in the data source. On the inside, every one of those virtual child elements is generated using the data retrieved from the current record in the data source and based on the element template.
Template is an element that you want to be replicated for every record in the data source. You create the template to have a desired internal structure, for example, a template might be a <TR> element that contains <TD> elements, which display data from a database table. When you create a template for use with data source, you need to use the data fields provided by the data source in order to make virtual nodes correspond to records in the data source.contents
This example illustrates use of data sources, data fields and templates to generate an HTML document containing a table with data from CUSTOMER table in DBDEMOS.
The source code is located in Demos\HTML\DBTable directory of your XVCL installation.contents
Web applications often have UI elements that are used over and over again. For example, in a web application that often requires users to enter date you might have a calendar control consisting of HTML table with 3 combo-boxes for selecting day, month and year.
The strength that distinguishes XVCL from Template/Tag based technologies, like Page Producer, is the simplicity and safety of reusing code by creating new components in addition to existing ones.
Creating new components is simple because you have a whole library of standard HTML components to use as your starting point - a base class and building blocks for your new component. Once you've built your first component, you can reuse it to create another component and so forth.
Creating new components is safe, because you don't need to worry about such typical mistakes like forgetting to put a closing tag, typos, breaking containership relations. XVCL has built in mechanisms for validating hierarchies of elements and attributes and new components are treated exactly like standard ones in this respect.
XVCL has a component design convention similar to one in VCL. All components have an immediate "Custom" ancestor. For example, TJvxHTMLDiv component, which encapsulates <DIV> element descends, from TJvxHTMLCustomDiv class. "Custom" ancestor defines all functionality of a component but doesn't publish any interface, so that you can use "custom" class as an ancestor for your own components that are similar to the standard component but need to have a different interface.
Typically you will be using TJvxHTMLCustomDiv or TJvxHTMLCustomSpan classes as ancestors for your new HTML components.
If you are creating a customized version of a standard HTML component, you don't need to do anything special about node name. But if you are creating a new component, you would need to set it's node name in the constructor using SetNodeName method.
constructor TMyComponent.Create(Owner: TComponent); begin inherited; SetNodeName('MyElement'); end;
For components that expose a large number of predefined attributes or elements, such as a typical HTML element that can have more than 10 standard attributes, XVCL provides specific methods that can to be used to create such standard predefined nodes. First of all, you need to declare fields and properties for your new standard attributes and elements.
Note the use of "Protected" attribute and element classes for the new properties. A set of "Protected" classes is defined in JvxStdNodes unit to be used for predefined attributes and elements. All "protected" classes have read-only node name that cannot be changed by client code. That's what predefined attributes and elements need to be most of the time - nodes that have predefined name and a value that can be changed.
type TMyComponent = class(TJvxHTMLCustomSpan) private FMyAttribute: TJvxProtectedStringAttribute; FMyElement: TJvxProtectedStringElement; published property MyAttribute: TJvxProtectedStringAttribute read FMyAttribute; property MyElement: TJvxProtectedStringAttribute read FMyElement; end;
TJvxNode introduces two virtual methods that can be overridden to create predefined nodes - DefineAttributes and DefineElements. Using these methods is not mandatory, you can use your component's constructor to instantiate your predefined attributes and elements.
procedure TMyComponent.DefineAttributes(DefineAttribute: TJvxDefineNodeProc; Data: Pointer); begin inherited; DefineAttribute(FMyAttribute, 'FMyAttribute', TJvxProtectedStringAttribute, Data); end; procedure TMyComponent.DefineElements(DefineElement: TJvxDefineNodeProc; Data: Pointer); begin inherited; DefineElement(FMyElement, 'FMyElement', TJvxProtectedStringElement, Data); end;
Since NodeName property is read-only unless you explicitly set it to be read-write in your components, in order to set the node name of a predefined attribute or element you need to get around of that protection using hard typecasting to TJvxExposedNode class. Note that design of NodeName property is still being worked on, this code might change in the future.
constructor TMyComponent.Create(Owner: TComponent); begin inherited; TJvxExposedNode(MyAttribute).NodeName := 'MyAttribute'; TJvxExposedNode(MyElement).NodeName := 'MyElement'; end;
Your new custom components can participate in the process of document validation by overriding one or more of three validation methods: ValidateParent, ValidateAttribute and ValidateElement. These methods are being called whenever an attribute or an element is being inserted into another element. Raising an exception from any of these methods will not allow that insertion to take place. Default implementations of ValidateAttribute and ValidateEelement methods defined in TJvxNode class always raise an exception. So you will need to specifically enable attributes and elements that you want to be able to insert in your custom component.
Note that validation nodes defined using DefineElements and DefineAttributes methods is done automatically.
The following example makes it possible to insert any inline HTML elements into the custom component. Note that inherited implementation is called so that exception will be raised for all other element classes.
procedure TMyComponent.ValidateElement(Element: TJvxNode); begin if Element is TJvxHTMLCustomInlineElement then Exit; inherited; end;
This example illustrates creation of custom components in XVCL. Two custom components are created in this example - TLookupEdit (control similar to a combo box but having a lookup button instead of drop down button and drop down list) and TCalendar (control consisting of 3 combo boxes for entering date as month, day and year).
The source code is located in Demos\HTML\Advanced Form directory of your XVCL installation.contents
XVCL is a component-based framework for building HTML and other Document and Document/View based applications. Although it's not available at this time, XVCL will eventually provide a sophisticated two way design time support for visual document development supporting visual inheritance and visual aggregation.
XVCL is an alternative to traditional Template/Tag based technologies. It has both advantages and drawbacks compared to Template/Tag solutions. It's typically easier to use Template/Tag for simple HTML applications but the value of component based architecture grows with the size and complexity of the application. The bigger and more complex the application is - the harder it is to build with Template/Tag and easier with component-based architecture.
XVCL is an open source project which means that it is free, comes with full source code, but it doesn't have any warranty and support is done only through mailing list. If you are serious about using XVCL, we highly recommend getting in touch with the developers, giving them your feedback, suggestions, etc.contents
Located at http://xvcl.sourceforge.net this web site is a home of XVCL project, you can download the most recent released version of the code, find news and other information about the project.
For those who want to get deeper inside the project, the control center located at http://sourceforge.net/projects/xvcl has much more information for developers. You can find detailed information on when the next version will be released, what features are going to be included, current development progress, etc.
MSDN Online http://msdn.microsoft.com
DevEdge Online http://developer.netscape.com
World Wide Web Consortium http://w3.org
Copyright © 2000-2001 XVCL