Application structure

Last modified
Saturday, December 29, 2018 - 03:29

Components

  • Browser/Javascript based web-application
  • Request handling
  • Perl application logic (mostly left over from pre-1.3)
  • PostgreSQL based authentication and authorization framework
  • PL/pgSQL based stored procedures (application logic)
  • PostgreSQL based data storage (tables) with SQL and PL/pgSQL based data integrity checks

Browser/web application

Before 1.5, all state changes in the browser were handled through the traditional CGI paradigm of "Submit+reload page", with some minor Javascript (JS) helpers to hide/show screen sections.

As of 1.5, there are other options due to more tight integration with the Dojo framework. In 1.5 pages are still reloaded using the "Submit+reload page" paradigm (mostly), but instead of letting the browser do so in a frame, the reloads are handled as asynchronous XHR requests.

Request handling

Webserver/Perl web-glue

Multiple web-frontends are supported, through the web-glue framework Plack. For development purposes, Starman is the easiest way to get started.

Dispatching

The general dispatch cycle works like this:

  1. The PSGI compatible server receives a request
  2. Custom-LedgerSMB Plack middleware performs request-wrapping functions, including
    1. Verification of credentials
    2. Loading the required workflow script
  3. Plack parses the request and dispatches to the configured route handlers
    1. Dispatch for pre-1.3 code
    2. Dispatch for post-1.3 code

Note that dispatching differs between pre- and post-1.3 code, but that the dispatch mechanism described below was implemented in the 1.6 development cycle.

Dispatching to post-1.3 code

After the Middleware wrappers have done their job, this sequence of events occurs:

  1. The function psgi_app in LedgerSMB::PSGI receives the request environment
  2. A LedgerSMB::Auth object is instantiated
  3. A LedgerSMB object is instantiated, from the request data and the LedgerSMB::Auth object
  4. A request-local environment is set up binding global variables to the values from the request (e.g. $LedgerSMB::App_State::User)
  5. The request is dispatched to the script's entry point, with the LedgerSMB instance as a parameter
  6. The entry point returns the PSGI result triplet to the dispatcher (psgi_app)
  7. The dispatch routine cleans up after the request, committing the transaction on success or rolling back the transaction in case of error and "unbinding" the global variables
  8. The dispatch routine returns the triplet to the Plack caller

Dispatching to pre-1.3 code

  1. The PSGI "app" returned by "old_app" in LedgerSMB::PSGI sets up a full CGI environment based on the PSGI environment
  2. After creating a full CGI environment, the STDOUT handle is bound to a temporary file
  3. The executing process is forked (in the _run_old() function of LedgerSMB::PSGI)
  4. The forked process transfers control to 'old-handler.pl' for request dispatch
  5. old-handler sets up a $form object (LedgerSMB/Form.pm) and creates a database transaction
  6. old-handler loads a 'workflow script' from old/bin/
  7. old-handler invokes the function specified in the 'action' query parameter
    Note: this could also be an 'action' or 'nextsub' POST parameter
  8. the invoked action generates the response by printing bits and pieces of the required HTML response inline with the code to decode web input and handling state change
  9. old-handler.pl cleans up after the request, committing the transaction on success or rolling back in case of an error
  10. the forking process continues processing by reading the CGI output generated by the forked process
  11. the request handler passes the PSGI response triplet to the Plack caller based on the parsed CGI output

Perl application logic

 

  1. The entry point constructs ORM mapper objects where necessary
  2. The entry point invokes the required state changes where applicable
  3. The entry point determines which output screens to generate, selecting a template from the UI/ directory
  4. The entry point passes the collected results and template to the rendering engine (LedgerSMB::Template::UI)
  5. The rendering engine generates the output, request headers and result code

Retrieving database information

 

Changing database information state

 

Database documentation

Ledgersmb database documentation.