Hi, The following is a quick summary of P5EEx::Blue with lots of references to the web documentation.
Stephen -------------------------------- INTRODUCTION TO P5EEX::BLUE -------------------------------- I. Getting Started Before digging in to the code of P5EEx::Blue, it is good to look around the P5EE web site. http://www.officevision.com/pub/p5ee/ Then explore the API documentation (which is of course not complete, but nonetheless very informative). http://www.officevision.com/pub/p5ee/software/htdocs/api/ In particular, the various services that form the building blocks of P5EE applications are summarized. http://www.officevision.com/pub/p5ee/software/htdocs/api/overview-summary.html A quick look at the list of classes which represent *interfaces* to the P5EE services and the various completed (and planned) *implementations* of those service tell a great deal about what each service is supposed to do. You can, of course, explored the detailed API of each service if you choose. http://www.officevision.com/pub/p5ee/software/htdocs/api/allclasses-frame.html The inheritance relationship of the classes can be seen at a glance. http://www.officevision.com/pub/p5ee/software/htdocs/api/overview-tree.html II. Architectural Principles * Pluggable Services The P5EEx::Blue is like a software backplane for many services required by an enterprise application. Into that backplane plug the P5EE Services. There may be many implementations of each of the P5EE Services, making for an almost limitless array of possible combinations. (Hopefully, favorites will emerge.) * Separation of User Interface, Business Logic, and Data Storage These three layers of software need to be distinct and separate for maximum leverage of enterprise assets and maximum flexibility of growth of the software. For web applications, the user interface is implemented with Widgets and Templates. The business logic is coded in Entity Widgets and Procedures. The data storage logic, including locking and transactional facilities, is controlled by the Repository. * Universal Access Any Business Logic coded anywhere in the Enterprise should be accessible from everywhere in the Enterprise. Similarly, any Data stored anywhere in the Enterprise should be accessible from everywhere in the Enterprise. SOAP is the primary protocol envisioned for this task, although others are also possible. This allows for the User Interface, Business Logic, and Data Access components to be located on different machines. It also provides for sharing of data and logic with programs written in other languages. * Component-Based, Data-Driven Programming A large amount of the application development should be done by assembling pre-programmed application components merely by configuring them in a configuration file. The development may be completed by extending existing components with custom programming or creating entirely new components under the same programming model. III. Core Services There are three "Core Services": Context, Session, and Config. A Core Service is one that is not derived from P5EEx::Blue::Service but maintains the concept of "a pluggable implementation of an abstract service". * Context - abstracts all of the details of the runtime environment so that the same application can be deployed in a CGI Context, a mod_perl Context, or even FastCGI/PPerl/etc. The Context is responsible for maintaining the Session and dispatching events from the "event loop". In a stateless (i.e. HTTP) environment, this means restoring and saving the Session for each request and dispatching events from multiple requests, while masking this complexity from the rest of the application. * Config - configuration data may be stored anywhere, although a simple configuration file is the most common. The job of the Config service is to retrieve the configuration information from whatever sources (XML file, INI file, Properties file, perl file) with the desired level of validation/caching/etc. and return a perl data structure of the appropriate form. * Session - All runtime data is stored in the Session object, which is implemented as a deeply-nested perl data structure. The differences between the different types of Session implementations is how they store themselves. The Session data structure is made up of two branches: the "store" and the "cache". The "store" is the minimum amount of information that, along with the Config, can recreate the "cache". The "cache" represents the runtime state of all Services, including Widgets (UI and Entity). IV. Standard Services The "Standard Services" are different types of application components used to build an application. They are all derived from the Service class. * Serializer - transforms a perl struct to a scalar and back * Security - provides authentication and authorization * Widget - a user interface component or a business logic component * Repository - a data store (RDBMS, File, Berkeley DB, etc.) * TemplateEngine - encapsulates template system details, allowing P5EE to be used with any popular template engine * LogChannel - a logging channel through which messages may be logged. * Messaging - an asynchronous message queue with configurable quality of service. may be broadcast to many recipients and may be replied to multiple times by each recipient. * Procedure - a (potentially remote and/or asynchronous) procedure which may be executed. Every procedure has only one set of results (i.e. one "reply"). * SharedDatastore - a simple data storage area which is shared between processes (like MLDBM) * SharedResourceSet - implements locking for synchronizing access and modification of shared resources When the application wishes to use a Service, it simply requests it by name from the Context. $w = $context->widget("users.table"); or $w = $context->service("Widget", "users.table"); The application does not need to know what actual class implements the widget. It just trusts that the call interface for the specific type of Service will be honored by the implementation. The framework allows for new Services to be added easily. V. Application Example A quick CGI application using standard components can consist of: * p5ee.conf (in the cgi-bin directory) * app.pl (in the cgi-bin directory) * SQL files (DDL to create tables in the database) The files themselves are largely self-explanatory and illustrate the power of the framework, transforming complex programming tasks into assembly and configuration tasks. (Of course, someone has to program the complex components!) ;-) The "p5ee.conf" file in the P5EEx::Blue distribution looks like this. ############################################################################# # $Id: p5ee.conf,v 1.1 2002/04/14 03:56:24 spadkins Exp $ ############################################################################# perlinc = /usr/ov/acoc/dev/src/P5EEx-Blue, /usr/ov/acoc/dev/lib/perl5/5.6.0 debugmode = record showsession = 1 gzip = 1 configFile = demo.pl defaultWname = report debug = 0 debugfile = debug.out scriptUrlDir = /cgi-bin/pub/p5ee scriptDir = /usr/ov/acoc/dev/p5ee/P5EEx/Blue/cgi-bin htmlUrlDir = /pub/p5ee/software/htdocs htmlDir = /usr/ov/acoc/dev/p5ee/P5EEx/Blue/htdocs ttTemplateDir = /usr/ov/acoc/dev/p5ee/P5EEx/Blue/template/ttdemo The "demo.pl" file in the P5EEx::Blue distribution could be narrowed down to the following. $data = { ######################################################################### # $Id: demo.pl,v 1.3 2002/04/19 14:38:44 spadkins Exp $ # NOTE: this is after the "$data = {" line for a reason ######################################################################### WidgetType => { table => { widgetClass => 'P5EEx::Blue::Widget::HTML::DataTable', repository => 'db', table => 'person', headings => [ "ID", "Last Name", "First Name", "Address", "City", "State", "Home Phone", "Sex", "Birth Date" ], columns => [ "person_id", "last_name", "first_name", "address", "city", "state", "home_phone", "gender", "birth_dt" ], keycolidx => [ 0 ], scrollable => 1, sortable => 1, filterable => 1, editable => 1, }, app => { widgetClass => 'P5EEx::Blue::Widget::HTML::AppFrame', title => "P5EE Reporting and Data Maintenance", bgcolor => "#cccccc", text => "#000000", link => "#996600", vlink => "#996600", alink => "#996600", leftmargin => "0", topmargin => "0", rightmargin => "0", bottommargin => "0", }, }, Repository => { default => { repositoryClass => 'P5EEx::Blue::Repository::DBI', dbidriver => "mysql", dbname => "p5ee_demo", dbuser => "dbuser", dbpass => "dbuser7", table => { person => { prikey => [ "person_id" ], }, }, }, }, Widget => { report => { widgetType => 'app', }, 'report.selector' => { widgetClass => 'P5EEx::Blue::Widget::HTML::SelectorView', selected => "1.1", node => { 1 => { open => 1, value => 'Reports', icon => 'calendar.gif' }, 1.1 => { open => 1, value => 'People', wname => 'table', }, }, }, table => { widgetType => 'table', }, }, };