Difference between revisions of "Xebra Documentation"

(Example)
Line 441: Line 441:
 
====Example====
 
====Example====
 
For the forms framework we will use a simple display of reservations with an input mask and delete command links.
 
For the forms framework we will use a simple display of reservations with an input mask and delete command links.
 
 
<xml>
 
<xml>
<f:form>
+
<table>
<xeb:iterate list="global_state.db.reservations" variable="reservation" type="RESERVATION">
+
<tr>
<xeb:display feature="#{reservation.name}"/>
+
<td>Name</td>
<xeb:display feature="#{reservation.date}"/>
+
<td>Date</td>
<f:command_link label="Delete" action="delete" variable="reservation" />
+
<td>Persons</td>
</xeb:iterate>
+
<xeb:container render="authenticated_admin">
</f:form>
+
<td>Delete</td>
 +
</xeb:container>
 +
<xeb:container render="not_authenticated_admin">
 +
<td>Details</td>
 +
</xeb:container>
 +
</tr>
 +
<f:form>
 +
<xeb:iterate list="global_state.db.reservations" variable="reservation" type="RESERVATION">
 +
<tr>
 +
<td><xeb:display feature="#{reservation.name}"/></td>
 +
<td><xeb:display feature="#{reservation.date}"/></td>
 +
<td>
 +
<f:command_link label="Delete" action="delete" variable="reservation" />
 +
</td>
 +
</tr>
 +
</xeb:iterate>
 +
</f:form>
 +
</table>
 +
<h2>New Reservation</h2>
 
<f:form variable="new_reservation" class="RESERVATION">
 
<f:form variable="new_reservation" class="RESERVATION">
<f:input_text value="name" name="a_name" text="#{new_reservation.name}" />
+
<table>
<f:input_text value="date" name="a_date" text="#{new_reservation.date}" />
+
<tr>
 
+
<td>Name</td>
<f:button value="Save" action="save" type="submit" />
+
<td><f:input_text value="name" name="a_name" text="#{new_reservation.name}" /></td>
 +
</tr>
 +
<tr>
 +
<td>Date</td>
 +
<td><f:input_text value="date" name="a_date" text="#{new_reservation.date}" /></td>
 +
</tr>
 +
<tr>
 +
<td colspan="2">
 +
<div align="center">
 +
<f:button value="Save" action="save" type="submit" /></div>
 +
</td>
 +
</tr>
 +
</table>
 
</f:form>
 
</f:form>
 
</xml>
 
</xml>

Revision as of 10:56, 30 June 2009


Architecture Overview

(img)

  1. The Xebra HTTP Plugin (Apache Module or IIS7 Handler) forwards a request from the HTTP server to the Xebra Server and waits for a response.
  2. The Xebra Server forwards a request to the appropriate web application.


Website Development

A Xebra Web Application consists of two parts: The xeb-files and the controllers. Xeb-files consist of html code with embedded xeb-tags. They are translated to servlets. Controllers are Eiffel classes that connect the servlets to the rest of the Eiffel classes. Features of controllers can be invoked from within a servlet. Typically, web designers create xeb-files with a html editor and at the same time, web developers create controllers to provide business logic to the servlets. The web application is then translated which means that the xeb-files are generated to servlet eiffel classes and the whole webappliation is compiled to an executable file. The translation and compilation of the web application is initiated by the xebra server.

For a step by step guide on how to create a web application see tutorials.

Comparison to other technologies

Some of the features of Xebra are:

  • Fully XML compatible for ease of xeb file validation
  • Mapping of forms to objects and validation framework
Project Language

Ajax

MVCframework

MVC Push/Pull

i18n & l10n

ORM

Testing framework(s) DB migration framework(s) Security Framework(s) Template Framework(s) Caching Framework(s) Form Validation Framework(s)

Xebra

Eiffel

Can be added later on (using for instance Script.aculo.us)
Yes
Pull
planned
No
Contracts, Unit Tests

planned
Yes
planned
Yes

Apache Struts

Java

Yes Yes Push & Pull Yes Yes

Unit Tests



Yes
Yes

ASP.NET MVC

ASP.NET

Yes Yes Push
ORM-independant

Unit Tests


ASP.NETForms Auth

pluggable (default is WebForms) Yes Yes (client-side via plugins)

Drupal

PHP

jQuery

Yes[2][3]


Yes[4][5]

multiple (CCK, QCubed)[6]

simpletest, devel Schema API

OG, Node Privacy By Role,ACL, Taxonomy Access List

PHPTemplate, Smarty, XTemplate, others

builtin,memcache,APC

Form API

Google Web Toolkit

Java,Javascript

Yes

Yes , no direct data access

JUnit(too early),jsUnit(too difficult),Selenium(best)

No



Ruby on Rails

Ruby

Prototype,script.aculo.us

ActiveRecord,Action Pack

Push Localization Plug-in

ActiveRecord

Unit Tests, Functional Tests and Integration Tests

Yes Plug-in Yes Yes Yes

Seaside

Smalltalk

Prototype,script.aculo.us, etc.



Yes

GLORP,Gemstone/S, etc.

Unit Tests, SUnit



No, intentionally

Magritte

Sphere

PHP5

Toolkit Independent Yes Push, supports Helpers Yes

Active Record Pattern

Unit Tests


via module plain PHP by default, can use Smarty or other via module, APC, etc via module

Spring

Java


Yes
Yes

Hibernate, iBatis, etc



Spring Security (formerly Acegi)

Commons Tiles,Velocity, etc.

ehcache etc. Commons Validator

Zend

PHP5 (>=5.2.4)

Toolkit-independent Yes Push & Pull Yes Table and Row data gateway

Unit Tests

Yes

ACL-based

Yes Yes Yes

Xebra Libraries

Page

The page libraries consists of the core tags needed for page configuration and composition. The Tags are:

Tag Description
<page:controller class="..." />

Defines the controller which should be used for the xeb page.

<page:declare_region id="..." />

Declares a region at the specific point in the xeb page where including pages can add specific html code.

<page:define_region id="...">
...
</page:define_region>

Can only be used inside a page-include tag. Will insert the content into the templates regions (with the same id). See page-include.

<page:include id="..." />

Includes an other xeb page. If the included page has declare-region tags they have to be implemented with define-region tags.

</page:fragment>

If used the page is not transformed to a servlet.


Example

This example shows the workings of the template framework. It consists of a master page which acts as a template and three different types of usage of this template.

master.xeb

<html>
<page:controller class="DEFAULT_CONTROLLER"/>
<body>
<h1>
<page:declare_region id="greeting" />
</h1>
<page:declare_region id="form" />
</body>
</html>

The master page is "deferred", since there are page:declare_region tags. The translator detects the undefined regions and doesn't generate a servlet from this xeb file.

slave1.xeb

<page:include template="master">
<page:define_region id="greeting">
Hello, I'm Slave 1
</page:define_region>
<page:define_region id="form">
Other region
</page:define_region>
</page:include>

slave1.xeb uses master.xeb as a template and includes it via the page-include tag. Since master.xeb declares two regions, slave1 defines them. The content of the define-region tags are inserted at the locations of the respective declare-region tags of the template. From this xeb file a servlet is generated. Additionally since it's not declaring any controller all controller calls are redirected to the ones in the template.

slave2.xeb

<page:include template="master"
<page:define_region id="form">
Other region 2
</page:define_region>
</page:include>

Templates can also be just imported partially. In slave2.xeb just the "form"-part of the template is implemented. This means that slave2.xeb is itself a template and will not be translated to a servlet.

slave3.xeb

<page:include template="slave2.xeb">
<page:define_region id="greetings">
</page:define_region>
</page:include>

This last example uses slave2.xeb as a template, which has one remaining region to implement: "greetings. The controller is still inherited from master.xeb, that is, controllers are transitive.

With these techniques we would be able to minimize duplicated code and hence errors in the xeb files, which are difficult to debug.

Xeb

Tag Description
<xeb:call feature="..." />

Calls the feature on the controller on render-time.

<xeb:loop times="..." >
...
</xeb:loop>

Loops its content "times" times.

<xeb:redirect url="..." />

Redirects the server to a new page at "url". The redirect is done server internally.

<xeb:iterate list="..." variable="..." type="...">
</xeb:iterate>

Iterates over a list (defined with "list" as a controller call). The current item is stored in "variable" which is of type "type". This variable is then available for its children.

<xeb:container>
...
</xeb:container>

This simple tag just groups parts of the site. Can be used to conditionally render some parts with the "render" attribute.

<xeb:display feature="..." />

The display tag simply displays what is written in feature.

Form

Tag Description
<f:form class="..." variable="...">
</f:form>

All form tags have to be contained in a f-form. A variable and class can be optionally defined to automatically wrap input forms to an object.

<f:button value="..." action="..."/>

A button is a normal html button. It is associated with a controller function ("action") which is executed if the validation of all inputs field where successful. The automatically wrapped object is then passed to the action. The value designates the Label on the button.

<f:input_text value="..." name="..." text="..."/>
<f:input_secret value="..." name="..." text="..." />

These two input fields are basically the same. The designated normal html inputs. Additionally they provide a name which makes them identifiable for validation output. f-validator tags can be added to the inputs to define validators.

<f:textarea value="..." name="..." text="..." rows="..." cols="..."/>

Basically the same as the input fields but with some additional auxiliary textarea-specific attributes (rows, cols).

<f:command_link label="..." action="..." variable="..." />

A command link is a html link. It acts though like a button and executes the defined action on the controller. If a variable is defined, it will be passed to the action (feature). Variable names can be used from f-form or xeb-iterate.

<f:validator class="..." />

A validator validates an input. It can be added to input fields (or textareas) to check the input.

<f:validation_result name="..." />

Outputs potential validation errors coming from the input field with the name "name".

Example

For the forms framework we will use a simple display of reservations with an input mask and delete command links.

<table>
	<tr>
		<td>Name</td>
		<td>Date</td>
		<td>Persons</td>
		<xeb:container render="authenticated_admin">
			<td>Delete</td>
		</xeb:container>
		<xeb:container render="not_authenticated_admin">
			<td>Details</td>
		</xeb:container>
	</tr>
	<f:form>
	<xeb:iterate list="global_state.db.reservations" variable="reservation" type="RESERVATION">
		<tr>
			<td><xeb:display feature="#{reservation.name}"/></td>
			<td><xeb:display feature="#{reservation.date}"/></td>
			<td>
			<f:command_link label="Delete" action="delete" variable="reservation" />
			</td>					
		</tr>
	</xeb:iterate>
	</f:form>
</table>
<h2>New Reservation</h2>
<f:form variable="new_reservation" class="RESERVATION">
<table>
	<tr>
		<td>Name</td>
		<td><f:input_text value="name" name="a_name" text="#{new_reservation.name}" /></td>
	</tr>
	<tr>
		<td>Date</td>
		<td><f:input_text value="date" name="a_date" text="#{new_reservation.date}" /></td>
	</tr>
	<tr>
		<td colspan="2">
		<div align="center">
		<f:button value="Save" action="save" type="submit" /></div>
		</td>
	</tr>
</table>
</f:form>

Tag Attributes

While most tag attributes are plain text and thus static, sometimes it is useful or even necessary to use dynamically bound attributes. In Xebra there are two different types of dynamic attributes:

Tag Description
... attr="%=call%"...

Call designates a controller feature which returns a STRING.

... attr="#{variable.name}"...

Uses a - predefined (form/iterate) - variable to retrieve a value.